Example

Embed an agent in your process with SDK sessions

The five in-process rules observed in sdk.test.ts: subscribe first, say steer or follow-up while streaming, and let SessionManager own the history.

An SDK session moves the agent into your own Node.js or Bun process: createAgentSession() returns a typed AgentSession, and the events you once parsed out of a pipe arrive as objects that keep the cumulative partial snapshots the JSON stream strips. Inside your process, rules the terminal used to handle silently become yours to state. Everything here is observed — sdk.test.ts drives a real AgentSession whose provider is scripted, on Pi 1.0.4.

Run it

Use Pi 1.0.4 and the example repository’s test runner. The canonical file is examples/ch34-sdk/sdk.test.ts: it builds a real AgentSession through the shared harness, scripts the model with the faux provider, and asserts the five rules below. There is nothing to configure, because the model is scripted.

The shape of the stream is illustrative (not a canonical file): subscribe before prompting, because a fast completion can arrive first:

const unsubscribe = session.subscribe((event) => {
  if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
    process.stdout.write(event.assistantMessageEvent.delta);
  }
});
await session.prompt("Explain this repository");
unsubscribe();

The in-process lifecycle

Stage What happens Why it matters
subscribe() Attach before the prompt A fast completion can arrive first
prompt() Resolves only when the run finishes, retries included The host never picks a completion event
Streaming message_update Typed objects carrying cumulative partial snapshots The detail the JSON transformation strips
steer() / followUp() The only legal way to queue input while streaming prompt() without either rejects
dispose() Aborts work, removes listeners, stops delivery Skipping it leaks the agent

Expected outcome

sdk.test.ts assertion What the test observed
Typed deltas arrive Deltas join to the whole answer, more than one delta, and getLastAssistantText() returns it
Steer or follow-up while streaming A plain prompt() rejects; steer() and followUp() both return "queued", and the run finishes cleanly
SessionManager is authoritative A forged agent.state.messages never reached the provider; the real earlier question did
In-memory manager getSessionFile() is undefined — no file is written
dispose() A listener receives nothing further after disposal

Mechanism and limitations

Documented: sdk.md (1.0.4) specifies createAgentSession(), subscribing before prompting, the "queued" / "handled" return of steer() and followUp(), SessionManager as the owner of the persisted or in-memory entry tree (assigning session.agent.state.messages does not replace that context), and dispose() releasing the agent’s subscriptions. Observed: sdk.test.ts runs all five rows above against a real AgentSession. The chapter’s no-argument createAgentSession() is documented, not run: it needs a real provider, and its default SessionManager writes a session file unless you pass SessionManager.inMemory().

The deltas are scripted, so this shows the event plumbing, not a real model’s behaviour. Embedding Pi is not a security boundary: your process’s extensions, credentials, files and network are the agent’s, and restarting Pi means restarting your service. It also does not show the asymmetry that SDK sessions do not load codemode, tool_search or MCP as built-in extensions the way the CLI does.

Full source and test .

Understand this example

Copy this prompt into your AI tool. No code runs here.

Apply this example

Copy this prompt into your AI tool. No code runs here.