Skip to main content
The in-process runtime is the default. When you call NewAgent without Temporal or Restate options, the agent loop runs directly inside your Go process — no external orchestration server. It is also durable by default: every LLM call and tool execution is journaled to disk via durable-go, so a process crash can resume instead of losing the in-flight run. Tune the journal or opt out entirely with local.WithLocalConfig — see Durability below.

Enable

Omit all Temporal and Restate configuration:
See Quickstart for a complete example.

How it works

When you call Run or Stream, the SDK executes the full agent loop in your process:
  1. Load conversation history and recalled memory (when configured)
  2. Call the LLM with the merged tool list
  3. Execute tool calls and append results
  4. Repeat until the model finishes or the iteration limit is reached
  5. Return the result or stream events back to your caller
Everything happens in-process — no network hops, no external orchestration.

Capabilities

All SDK capabilities are available on the in-process runtime:
  • LLM providers (OpenAI, Anthropic, Gemini, custom)
  • Tools, MCP, A2A, sub-agents
  • Conversation (in-memory), memory, retrieval (RAG)
  • Streaming, AG-UI events, hooks
  • Human-in-the-loop approvals
  • Budget (WithBudget)
  • OpenTelemetry observability
  • Durable execution and reconnect (GetAgentRun / GetAgentStream) — on by default, see Durability
Horizontal worker scaling (NewAgentWorker / multiple registered endpoint deployments) requires Temporal or Restate.

Durability

The in-process runtime journals every LLM call and tool execution to disk via durable-go — no WithLocalConfig call needed. If the process crashes mid-run, restart it (from the same working directory) and reconnect with GetAgentRun or GetAgentStream; already-completed steps are not re-executed. Unlike Temporal/Restate, GetAgentStream’s Events does not accept WithOffset(n) for n > 0 here — reconnect always replays full step history first (see Reconnect fidelity below), then continues live. Same split as Temporal: LocalConfig knobs build a default engine (like WithTemporalConfig); LocalConfig.Engine is a caller-owned engine for security and custom options (like WithTemporalClient).

SDK-built engine (default)

The SDK constructs a durable-go engine and manages its lifecycle. Import pkg/agent/runtime/local to tune the journal or opt out:
DataDir is exclusive-locked (in-process + OS flock). Running more than one process/replica against the same DataDir fails the second one’s engine creation. Give each replica a distinct DataDir (e.g. derived from hostname/pod name).
The default journal is plaintext JSON (input.json, step results). The SDK does not invent encryption or step-token keys.
a.Close() cancels in-flight local runs — this is not the same as a crash. Close closes the durable-go engine it owns, which cancels every in-flight run on that engine (not just the calling agent’s) and waits for that cancellation to be journaled before returning. Those runs become terminal (not resumable) — GetAgentStream / GetAgentRun return ErrRunAlreadyCompleted for them afterward, the same as a run that finished normally. On Temporal/Restate, closing the client does not affect server-side runs. Practically: a graceful shutdown handler that calls a.Close() while runs are in flight finalizes them; only an unclean process exit that skips Close (kill -9, OOM, panic before defer runs) leaves a run genuinely resumable via reconnect on the next process start.

Caller-owned Engine (payload codec, journal MAC, step-token key)

Use when you need at-rest encryption, a tamper-evident journal, or approval tokens that survive a process restart. You create and own the durable-go engine — the same pattern as Temporal Cloud / TLS via WithTemporalClient:
The agent does not close a caller-supplied Engine — you own its lifecycle and must call engine.Close() yourself. DataDir, AutoPurgeAge, Timeout, LockTimeout, and the other knobs are ignored when Engine is set (set them on NewEngine instead). Use the same codec and journal MAC key (or none) every time you open that directory — turning them on later against an existing plaintext tree is not a migrate. Step IDs, errors, and panic traces stay plaintext even with a codec. See durable-go data privacy.
See Durable Engine example for the full pattern.

Limitations

Handles from Run / Stream are same-process only in the sense that AgentRun/AgentStream values themselves don’t survive a restart — but the underlying run does (it’s journaled). Reconnect via GetAgentRun / GetAgentStream + the saved runID, the same public API used on Temporal/Restate. See Durable Execution.

Error handling

On in-process, errors are returned directly to the caller:

Run

Stream

Any panic inside a tool call is caught and returned as a RUN_ERROR event / error result, with the panic message included. The run does not propagate the panic to your caller.

When to use

Switch to a distributed runtime

Import a distributed runtime package and add its config option — no other code changes. (Crash recovery alone is not a reason to switch — in-process already has it; do this for horizontal scale, a client/worker split, or token-level reconnect fidelity.) Temporal:
Restate:
A running Temporal or Restate server is required. See Temporal or Restate.

Examples

Simple Agent

Minimal in-process agent with Run()

Stream

Streaming tokens and tool events in-process

Durable Agent (Local)

Zero-infrastructure crash/reconnect lab — kill and restart the process