Skip to main content
Version: 2.0

Workflows

An agent doesn't just respond to a single prompt. It moves through workflows — sequences of decisions, lookups, validations, and actions that produce an outcome a business cares about. This page is the conceptual chapter on how the agent does: how Vectara turns business processes into deterministic, auditable agent execution.

If your team can draw the workflow on a whiteboard, it can run as a Vectara agent — with audit trails, RBAC, HHEM grading, and approvals built in.

Why workflows, not free-form LLM loops

Most "agent frameworks" let an LLM decide what to do, when to do it, and when to stop. That works for demos. It fails the moment a real business process needs:

  • A specific step that must run, in a specific order.
  • A condition that has to evaluate correctly (refunds over $500 go to the manager, period).
  • An auditable record of which branch fired and why.
  • A guarantee that a jailbreak in one phase can't trigger a tool scoped to another.
  • A pause for a human approver — sometimes for days — without losing context.

Vectara agents are declarative state machines. The LLM still picks what to call within a step, but the platform picks which step runs next based on conditions you specify. The result: workflows that are deterministic where it matters, with the LLM's flexibility where it helps.

The primitives

A Vectara workflow is built from four primitives, each pulling its weight:

PrimitiveWhat it doesCanonical reference
StepsNamed phases of a workflow. Each step has its own instructions, scoped tool set, and output parser.Steps
Conditional routingnext_steps conditions decide which step runs next, evaluated against the previous step's structured output.Steps § routing
Structured outputsTyped JSON the LLM must produce. Downstream conditions read it via get('$.path'). The contract between steps.Structured outputs
Sub-agentsOther agents called as tools. Specialist workflows reusable across orchestrators.Sub-agents

These four primitives compose into any business process — refund approval, customer escalation, lead qualification, parts BOM generation, incident triage, HR onboarding, procurement gating.

Steps — phases of work

A step is a discrete unit of the workflow. It has:

  • Its own instructions — the LLM sees a different prompt in each step, so you don't need one monolithic mega-prompt.
  • Its own allowed_tools — tool scope narrows per step. Least privilege by default. A classifier step doesn't see the refund tool.
  • Its own output_parser — what shape the step emits.
  • Its own next_steps — conditions that decide where to go next.
{
"first_step": { "name": "classify", "next_steps": [ /* ... */ ] },
"steps": [
{ "name": "lookup", "next_steps": [ /* ... */ ] },
{ "name": "manager_gate", "next_steps": [ /* ... */ ] },
{ "name": "resolve", "next_steps": [ /* ... */ ] }
],
"reentry_step": "classify"
}

first_step is the entry. steps is the rest of the graph. reentry_step decides where second-turn user messages land — not necessarily back at intake.

Conditional routing — the agent's logic, in JSON

next_steps is evaluated in declaration order. First match wins. The last unconditional entry is the catch-all.

"next_steps": [
{ "condition": "get('$.intent') == 'refund' and get('$.amount') > 500",
"step_name": "manager_approval" },
{ "condition": "get('$.intent') == 'refund'",
"step_name": "auto_refund" },
{ "step_name": "general_handler" }
]

Conditions read the previous step's structured output via JSON-path. The routing logic lives in JSON, not in a paragraph buried in a prompt. That's how you make the agent's logic auditable, testable, and safe under jailbreak. The LLM can't talk itself into a different branch.

Structured outputs — the contract between steps

A step can be required to emit JSON matching a schema:

"output_parser": {
"type": "json",
"json_schema": { "required": ["intent", "order_id", "reason"] },
"store_as": "$.classification"
}

Downstream next_steps conditions read fields from $.classification.intent, $.classification.amount, and so on. If the LLM's output doesn't match the schema, the platform retries automatically.

This is the contract that lets workflows compose. A classifier step that emits {intent, order_id, reason} becomes a building block any downstream step can depend on.

Sub-agents — composition without coupling

A sub-agent is a full Vectara agent wrapped as a single tool. The parent calls it the same way it calls any tool; the called agent runs in its own session, with its own steps, tools, model, and secrets, and returns its result.

"approvals": {
"type": "sub_agent",
"agent_key": "manager_approval_agent"
}

What this unlocks:

  • Reuse across orchestrators. The same approvals sub-agent backs HR, procurement, and refunds. One source of truth for "how we approve things."
  • Specialist scope. A legal-review sub-agent uses a premium model and tight instructions, while the parent uses a cheaper model. Tune cost per task, not per company.
  • Bounded blast radius. A sub-agent runs in its own session; the parent doesn't see its turn-by-turn reasoning unless you pass context explicitly. Failures stay local.
  • Async-friendly. A sub-agent can pause cross-session for a human approver and resume when they reply — could be seconds, could be days.

Approvals — pausing for a human

Any step can call a sub-agent that pauses cross-session. The parent workflow holds. When a human approves (or denies) via webhook, the sub-agent returns and the parent resumes. The session metadata, the structured outputs already produced, and the conversation history are all still there.

This is how a refund-over-$500 workflow pauses for a manager. Or how an HR onboarding flow waits for IT provisioning to confirm. Or how a high-risk procurement waits for a CFO sign-off. No queues, no state machines, no custom orchestrator — it's a sub-agent that waits.

Reentry — second-turn messages route correctly

When a user sends a follow-up message, you usually don't want the agent to start over at intake. reentry_step is the hook:

"reentry_step": "followup_handler"

The follow-up handler has its own scoped tools and instructions. A session that started with a refund request and is now mid-conversation about the timing of the refund routes to the handler designed for that, not back to the classifier.

Workflows imagined

Every workflow below maps to a stepped agent:

DomainSteps
HR onboardingcollect docs → IT provision → schedule training → notify manager → completion check
Procurement approvalclassify → policy check → tier-based approver → write to ERP → notify requester
Customer escalationtier-1 KB search → tier-2 engineer sub-agent → human review → resolution log
Compliance reviewextract → classify clauses → red-flag check → legal sub-agent → status report
Lead qualificationenrich → score → route by ICP → write to CRM → schedule follow-up
Incident triageclassify → severity score → owner notify → KB search → status update → postmortem
Account openingKYC → AML check → credit score → tier assignment → approval → notification

Same primitives. Different corpora, different tools, different routing conditions. No platform release needed for any of them — they're declarative JSON your team writes and versions.

Why this beats hand-rolled orchestration

What you don't have to buildWhy it matters
A state machine engineSteps + next_steps is the engine — already running, already audited.
A queue for pending approvalsSub-agents pause cross-session natively. No SQS / Temporal / custom orchestrator.
A schema validator between phasesoutput_parser already validates against your schema and retries on failure.
A jailbreak defense at the routing layernext_steps evaluates structured fields, not prose. The LLM can't talk the router into a different branch.
A multi-tenant identity propagatorsession.metadata + $ref pass identity into every tool and corpora_search filter.
An audit trailEvery step transition, tool call, and structured output is a typed event streamed to your sink of choice.

This is the platform doing the workflow heavy lifting. Your team writes the steps; the platform runs them safely.