Skip to main content
The problem: Your organization already runs multi-step procedures — onboarding, provisioning, compliance checks — in an orchestration engine. You want the LLM to trigger those procedures without re-implementing steps inside the agent loop, and without the LLM improvising or skipping steps. The solution: Expose workflows as a custom tool (run_workflow). The LLM routes user intent to workflow_name and input; your WorkflowRunner executes the steps deterministically and returns the result. Steps run in order, retry on failure, and produce an auditable record — entirely inside your engine.

What deterministic means here

The LLM’s job is intent routing — mapping “onboard Alice” to workflow_name: onboarding, input: Alice. Your orchestration engine owns the procedure:
LLMYour orchestration engine
Pick workflow_name and inputExecute steps in defined order
Summarize WorkflowResult for the userRetry each step on failure
Ask clarifying questions before calling the toolEnforce side effects (email, provision, API calls)
Never skip or reorder stepsProduce an audit trail
This is different from asking the LLM to “figure out what steps to run” — the engine always runs the same steps for the same workflow name. Example: Workflows.

Tool pattern

type WorkflowRunner interface {
    Run(ctx context.Context, name, input string) (WorkflowResult, error)
}

a, _ := agent.NewAgent(
    agent.WithLLMClient(llmClient),
    agent.WithTools(NewWorkflowTool(yourRunner)),
)
Execute delegates to WorkflowRunner.Run and returns when the workflow reaches a terminal state (or the context deadline fires).

How the agent waits

User prompt → LLM calls run_workflow → Execute → WorkflowRunner.Run
  → engine starts workflow → steps run deterministically → WorkflowResult → LLM reply
One agent Run stays open until WorkflowRunner.Run returns — minutes or hours depending on workflow duration and any wait steps inside your engine. Pass the SDK’s ctx from Execute into your wait loop so deadlines propagate.

Wait steps inside orchestration

Workflows can pause on external events or human gates defined in your engine — the agent run stays open the whole time:
EngineWait / gate mechanism
Temporalworkflow.AwaitWithTimeout on a signal
ConductorHUMAN task
Argo Workflowssuspend template
Step Functions.waitForTaskToken
Size WithToolExecutionConfig and WithTimeout to cover the full workflow duration including any wait steps.

Timeout layers

LayerWhat it limitsConfigure
Per Run contextEntire agent callcontext.WithTimeoutalways wins
Agent runWhole turn (LLM + all tool waits)WithTimeout
Tool executeSingle run_workflow waitWithToolExecutionConfig
Orchestration engineIndividual stepsYour engine config
a, _ := agent.NewAgent(
    agent.WithLLMClient(llmClient),
    agent.WithTools(NewWorkflowTool(runner)),
    agent.WithAgentMode(agent.AgentModeAutonomous),
    agent.WithTimeout(2 * time.Hour),
    agent.WithToolExecutionConfig(agent.ExecutionConfig{
        Timeout:     2 * time.Hour,
        MaxAttempts: 1, // do not blindly re-trigger a started workflow
    }),
)
Default tool execution timeout is 30 minutes with up to 3 attempts if unset — raise it for workflow agents.
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Minute)
defer cancel()
result, err := a.Run(ctx, "Run onboarding for Alice", nil)
If the deadline fires, Execute returns context deadline exceeded — the workflow may still be running in your engine. Use idempotent workflow IDs and a status API in your runner for recovery.

Orchestration runners

Implement WorkflowRunner once per engine — map workflow_name + input to your API, wait until terminal, return WorkflowResult:
EngineWait until complete
In-processRun steps directly; no infrastructure needed (default in example)
TemporalExecuteWorkflow + run.Get(ctx, &result)
ConductorStart → poll until COMPLETED / FAILED
Argo WorkflowsSubmit → watch until phase Succeeded / Failed
Step FunctionsStartExecutionDescribeExecution
The example ships two runners: inprocess_runner.go (default, no infra) and temporal_runner.go (ORCHESTRATION_ENGINE=temporal). Add conductor_runner.go, argo_runner.go, etc. for other engines — only main.go changes when you swap runners. Workflow orchestration is independent of AGENT_RUNTIME — the agent can run in-process while your runner uses any backend. Example: Workflows.

Examples

Workflows

run_workflow tool with in-process and Temporal runners

Execution config

Per-operation timeout overrides

Execution config

Tool execute timeout and max attempts

Timeouts & modes

Agent run timeout and interactive vs autonomous

Tools

Custom tool implementation