Skip to main content
This page is for code that uses AgentBuilder, AgentExecutor, ToolRegistry and resumeAfterApproval(): the lower-level API the SDK started with. Those exports keep working and this page does not remove them; if you stay on them, see The executor API. The reason to move is that one createAgent() call wires tools, stores, approvals, sessions, retries and compaction, where the executor makes you assemble each of them and pass them to every call. createAgent() does not take every option the executor takes yet; see What createAgent() does not take yet before you start.

Before and after

One agent with a tool that needs approval, first with the executor API, then with createAgent(). Both use a scripted model, so they run offline and end with the same text, Sent the report to Sam., after the same pause.
The tool is the same defineTool() result in both. The agent keeps its own registry, approval store and provider, so deciding the pause needs only the approval id.

Mapping

What createAgent() does not take yet

These ExecuteOptions have no createAgent() option. Where there is a supported alternative it is named; otherwise keep that call on AgentExecutor.execute(). A run uses one API or the other: an agent that needs one of the “None” rows keeps that call on the executor, and can use createAgent() for the rest of the code.

Behavior differences

  • send() is one turn. A conversation is a separate object, agent.session(), which keeps the transcript and sends it with each turn; see Sessions. Code that built a message history by hand moves to a session.
  • A paused run resolves. A send() that reaches a needsApproval tool resolves with finishReason: 'awaiting-approval' and an approvalId; it does not throw. The pause stays with the agent, so agent.approvals.list() shows it and resolve() continues it without the registry or provider.
  • The default approval store is per agent and in memory. A pause survives a restart only with a durable store or approvalStore; see Choosing a store.
  • Retries are on by default for a model string: two retries of a failed model call. A provider instance you pass is not wrapped unless you set retry. See Provider retries and fallback.

Migrating step by step

  1. Tools first. Keep the defineTool() tools; drop the ToolRegistry and any addTool(key, config) call, and list the tools in tools.
  2. Replace AgentBuilder with createAgent({ name, instructions, tools }), and pass model or the provider you already pass to execute().
  3. Replace each AgentExecutor.execute() with agent.send() and each stream() with agent.stream(). Move maxSteps, limits and the other shared options to createAgent(). Keep a call on the executor if it needs an option from the “does not take yet” list.
  4. Replace resumeAfterApproval() with agent.approvals.resolve(). If approvals must outlive the process, pass the store you used as approvalStore.
  5. Move checkpointStore and its sessionId to store, and pass sessionId to send(). Use agent.session() where you kept a history yourself.
  6. Replace onEvent with ExecutionEvent by an AgentEvent listener, then move HookRegistry hooks into hooks.