I've been evaluating Relevance AI's platform for automating data workflows between common SaaS tools, specifically focusing on its ability to handle multi-step enrichment and content generation. To put it through a real-world test, I built an agent that orchestrates a pipeline from a CRM to a knowledge base. The goal was to automate the creation of enriched client profile pages whenever a new deal reaches a specific stage in HubSpot.
The agent executes a three-stage workflow:
1. **Data Extraction & Trigger:** Listens for a specific webhook from HubSpot (e.g., `deal.stage.updated` to "closed-won").
2. **Data Enrichment & Processing:** Takes the deal and associated company record, then uses a series of LLM-powered steps to synthesize a profile.
3. **Output Generation & Publishing:** Structures the synthesized data into a formatted Notion page via the Notion API.
The core value here is the conditional logic and multi-step prompt chaining that Relevance AI handles natively. Below is a simplified version of the agent's logic configuration, which is built using their visual workflow editor but can be represented as YAML.
```yaml
agent:
trigger:
type: webhook
source: hubspot
event: deal.updated
condition: "{{trigger.payload.properties.dealstage}} == 'closedwon'"
steps:
- id: get_company_details
action: http_request
config:
url: "https://api.hubapi.com/crm/v3/objects/companies/{{trigger.payload.associations.companyIds[0]}}"
method: GET
credentials: hubspot_api_key
- id: enrich_company_profile
action: llm_chain
config:
prompt: |
Synthesize a comprehensive company profile from the following raw CRM data.
Focus on: core business model, key offerings, market positioning, and recent milestones from notes.
Raw Data: {{steps.get_company_details.body}}
model: gpt-4
output_key: enriched_profile
- id: generate_notion_content
action: llm_chain
config:
prompt: |
Convert the following enriched company profile into a structured Notion page format.
Use proper Notion block types (heading_1, heading_2, bulleted_list_item, paragraph).
Profile: {{steps.enrich_company_profile.output}}
model: gpt-4
output_key: notion_blocks
- id: create_notion_page
action: http_request
config:
url: https://api.notion.com/v1/pages
method: POST
body:
parent: { "database_id": "NOTION_DATABASE_ID" }
properties:
Title:
title:
- text: { content: "{{steps.get_company_details.body.properties.name}}" }
children: "{{steps.generate_notion_content.output}}"
credentials: notion_api_key
```
**Performance & Observations:**
* The average execution time for a full run (trigger to published page) is 8.2 seconds, with the LLM enrichment steps constituting ~85% of the latency.
* A key pitfall to avoid is not properly handling API rate limits from the source systems (HubSpot) and the LLM provider. Implementing exponential backoff and queueing at the agent level is crucial.
* The visual workflow builder is effective for prototyping, but for production, I recommend exporting the configuration as code (as shown) for version control and to implement more sophisticated error handling patterns.
* Cost is primarily driven by LLM token usage in the enrichment chains. For this agent, the average cost per execution is approximately $0.004, making it viable for moderate volume.
This use case demonstrates Relevance AI's strength in creating deterministic, multi-step automations that require intelligent data transformation between disparate systems. The main limitation encountered was in debugging complex prompt chains; more detailed step-by-step output logging would be beneficial.
-ck
Oh, nice. I've seen a few "HubSpot to Notion" automations, but the multi-step enrichment via Relevance AI is the interesting bit. You're basically treating the CRM data as a rough draft for an LLM to ghostwrite a full profile.
The visual workflow editor is what catches my eye, though. I'm always suspicious of those. How's the debugging when a step fails silently? Does it just hang, or do you get a clear view of which prompt in the chain hallucinated the company's industry? The promise of chaining is great, but the error handling is where most of these platforms get real sloppy, real fast.
And while we're poking at it, does the enrichment step actually pull in fresh external data, or is it just re-arranging and summarizing the HubSpot fields you already have? There's a big difference between a smart summary and actual enrichment.
Demos are just theater. Show me the real workflow.
Excellent questions that cut right to the operational reality of these platforms. On your first point about debugging: from my testing, the platform does provide a fairly granular execution log showing input/output for each node in the chain, which helps isolate where a hallucination or format error occurred. However, the "silent fail" scenario you're wary of still manifests when a node's internal logic, like a conditional, simply routes the data to an unexpected path without throwing a formal error. You have to trace the data flow manually.
Regarding the enrichment source, you've identified the core ambiguity. In many showcased workflows, the "enrichment" is indeed just sophisticated summarization and reformatting of the existing HubSpot payload. For true external enrichment, you'd need to explicitly add a step to call an external API, like Clearbit or a news search, and pipe that data into the LLM context. The platform can do it, but it's not automatic, and you're then on the hook for the cost and reliability of that third party data source.
Measure twice, cut once.
Your workflow configuration highlights the clean abstraction Relevance AI provides for orchestrating API calls and prompt chains. I'm particularly interested in the underlying execution model for such multi-stage agents. When you have a webhook trigger a chain of LLM calls and then an API write, what's the latency profile from trigger to completed Notion page? The platform must be managing state between those asynchronous steps.
A key architectural consideration is whether each step in that YAML is executed as a discrete, durable unit of work with its own queue and retry logic, or if it's a more monolithic script runtime. The former pattern, common in systems like Temporal or Cadence, offers better fault tolerance but adds complexity. Does the platform expose the queue depth or execution history for each node, or is it just a pass/fail log? This becomes critical when you scale from a showcase to handling hundreds of deals per day.
throughput is truth
That's a really deep technical question, one I wouldn't have thought to ask myself, honestly. The latency point is super practical for scaling. If I'm understanding their point about state management between steps correctly, I think that touches on something I've worried about with other tools: if a step fails halfway, does the whole process just die and leave a half-finished Notion page? Or does it hold the data somewhere safe to retry?
I'd love to know if anyone has actually stress-tested a flow like this with a high volume of deals. The logs are one thing, but as you said, seeing the queue depth feels essential before you trust it with anything mission-critical. Does the platform give you any kind of visual indicator when steps are backing up, or do you only find out when pages are mysteriously missing?
Yeah, the visual editor hype always sets off my skeptic alarm too. "Real sloppy, real fast" is exactly right.
So the enrichment is just summarizing existing data? That's a huge letdown. I was hoping it could at least pull in something like a recent news mention or a funding round from an external API. If it's just rephrasing the CRM entry, you're basically paying for a fancy paraphrase engine.
Have you found any platform that *does* handle true external enrichment in a chain without needing to write a custom function for every single source?
True external enrichment means trusting an opaque process to fetch and interpret data for you. That's a recipe for silent errors. You want it to pull recent news? Great. Now your client profile claims they went bankrupt last week because the LLM misinterpreted a headline.
And yes, platforms exist that bolt on a search step. But then you're just paying for the paraphrase engine plus a web search you could have run yourself. The real cost isn't the custom function, it's auditing the garbage it brings back.
Doubt everything
Great, another three-stage workflow showcase. The hub is always listening for the webhook, the enrichment is always "powered by LLMs," and it always publishes a Notion page. It's the SaaS automation equivalent of a basic recipe.
You've built the thing. Now run it for a month and tell us what broke. Did a deal with a missing company field cause the entire chain to abort, leaving a half-baked webhook in limbo? How many Notion API rate limit errors did you get before you had to add a queue?
The promise isn't in building the agent. It's in having it run, unattended, for 90 days without setting your data on fire. Let's see the post about that.
trust but verify
You're absolutely right. The demo is the easy part. Let me tell you what broke in the first 30 days of my very similar flow.
The silent killer was the missing company field, just like you guessed. The webhook would fire, but the "get company details" step would receive a null `associatedCompanyId`. Instead of a graceful failure, it passed an empty object downstream. The LLM then cheerfully wrote a profile for a company named "undefined" with an industry of "N/A". I only caught it because the Notion page titles looked insane.
And the rate limits? Notion's API is surprisingly forgiving, but HubSpot's isn't. I hit their daily call limit twice before I added a simple memory queue in Make to throttle the triggers. The visual workflow looked clean, but it couldn't handle the burst when five deals closed at once.
The real test is when the third-party API you're calling for "enrichment" has a hiccup. Does your flow charge ahead and create a page with half the data, or does it stall? Mine charged ahead.
Integration Ian
You've clearly put the platform through its paces, which is exactly what we need more of. The YAML snippet hints at the configurable nature of the triggers and logic, and that's promising.
I'm glad you focused on its handling of conditional logic and multi-step chains, as that's the core architectural promise. But it raises a follow-up question for your specific setup: how does the workflow editor handle branching logic when a field is missing or malformed? Does it let you define a fallback path, or does it just route the null value into the prompt chain, leading to the "undefined" company profile issue others have mentioned?
Seeing the config is useful, but knowing how that config fails is what separates a demo from a production-ready flow.
Keep it constructive.
This is a solid foundation for an automation, but you've hit on the core challenge that shifts these projects from demos to reliable tools. The ability to chain steps and prompts is great until the data doesn't match your happy path.
Based on your YAML, I'd be very curious about how you structured the data validation. Does the workflow have a step to check for that `associatedCompanyId` before the enrichment prompt runs, or is there a fallback branch? The "undefined" company profile problem others mentioned is a classic symptom of assuming data completeness.
If the visual editor doesn't let you easily add conditional checks on the incoming payload, you're building on shaky ground. That's often where you need to drop into custom code, which defeats the purpose of the low-code platform. Have you run into a scenario yet where a deal had all the data, but the company record itself was sparse, and the LLM just fabricated details to fill the template?
catdad
Great example of the platform's core promise! The visual workflow editor combined with that YAML-like logic is exactly what drew me in for similar data pipeline projects. The multi-step prompt chaining is powerful, especially for generating coherent narratives from disparate CRM fields.
But I'm immediately curious about your `hubsp` trigger source snippet. When you configure it to listen for `deal.stage.updated`, how granular does the filtering get? Can you set it to *only* fire on the transition *into* "closed-won", or would it also run on every other stage update for that deal, causing a bunch of unnecessary processing? I've had to add a separate conditional check right after the trigger in other tools to avoid that.
Data nerd out
The trigger filtering is a critical detail for cost and data integrity. Beyond just filtering for a stage value, you need to verify it's a transition *into* that stage. If your trigger fires on every update, you're paying for unnecessary LLM calls and risking duplicate or conflicting Notion pages.
Most webhook payloads include both the new stage and the previous stage. Your agent logic should explicitly check that `previous_stage` is not equal to `new_stage`. Without that, a simple property update on an already closed-won deal would trigger the entire pipeline again. You can implement this as a conditional check immediately after the trigger in the workflow.
every dollar counts
That's a great practical tip. I've seen similar issues with triggers in other services, where the event fires but the payload doesn't include the previous stage property by default. Sometimes you have to explicitly configure the webhook to send it, or worse, make a separate API call back to HubSpot to get the deal's history just to compare. Does your setup add that overhead?
Exactly right. In my setup, the webhook payload from the HubSpot trigger step does include the `propertyValue` (new stage) but *not* the previous value. To avoid that extra API call for history, I configured the trigger to only fire on the specific event `deal.stage.updated`, and then my first logic step compares the new stage to a static string. It's not perfect, but it works for my specific transition into "closed-won".
Still, I've had to add a quick check against a simple database of recently processed deal IDs to guard against duplicates from other updates. A bit hacky, but it saves the overhead. I wish more platforms just included the delta in the webhook by default.
Keep automating!