AnyAgent

Sessions

Run one conversation across many turns, persist it, branch it, and steer it live.

A session is one conversation spanning many runs: open it with agent.session(), and each turn continues where the last left off. You never thread a session id by hand. These examples assume an agent from Run an agent.

Run turns

Works withClaude CodeemulatedCodexemulatedopencodeKilo CodeemulatedPiemulatedgooseGemini CLIAntigravityemulatedCursoragent.supports("resume")full matrix

session.run works like the agent’s own, returning the same awaitable, iterable handle:

const session = agent.session();
await session.run("Review this repo for unhandled rejections.");
const fixes = await session.run("Fix the issues you found.");
console.log(fixes.text);

Turns queue: a run called while another is in flight starts when it settles, threaded automatically. A failed turn rejects the turns queued behind it; calling run again retries from the last good point.

Persist and continue later

session.id is a plain string, set once the first turn reveals it. Store it anywhere and continue from any process:

const session = agent.session();
await session.run("Start reviewing this repo.");
await save("review-session", session.id);

// Days later:
const resumed = agent.session({ resume: await load("review-session") });
await resumed.run("Continue with src/.");

Conversation state lives with the CLI, so nothing else needs persisting. Iterating a turn surfaces the session event early, so you can persist the id before the first turn even ends.

Branch a conversation

Works withClaude CodeopencodeKilo CodePiagent.supports("forkSession")full matrix

Where the CLI can copy-on-resume (sessionFork: claude-code, opencode, Kilo Code, Pi), fork: true branches instead of continuing — session.id becomes the new conversation’s id:

const mainline = agent.session({ resume: saved });
const experiment = agent.session({ fork: true, resume: saved });

Resuming one id into two sessions without fork is a relay, not a branch: both continue the same conversation, in whatever order their turns arrive.

Which agents run sessions

Every built-in adapter except Cline runs sessions; agent.supports("resume") is the guard, and agent.session() throws where it is false. Agents that hold a live connection add steering, covered next; the Sessions column in the matrix marks them.

Steer a live session

Some agents hold a live connection, keeping one session open instead of respawning per turn. That native connection unlocks two things: steering the turn as it runs, and visibility into permission requests. Gate on session.supports("steer").

Steer a running turn

Works withopencodegooseGemini CLICursorsession.supports("steer")full matrix

session.steer(text) injects guidance into the turn that is currently running:

const session = agent.session();
const turn = session.run("Migrate config/ to TypeScript.");
if (session.supports("steer")) {
  session.steer("Skip the legacy directory.");
}
await turn;

Steering adds guidance to an autonomous turn; it does not add an approval gate. On agents without a live connection, steer throws UnsupportedCapability; guard and degrade, as with any capability.

Watch permission requests

A live agent asks permission before some tools. AnyAgent answers for you, allowing so a run never blocks, and surfaces each exchange as a permission-request event carrying the agent’s own options:

for await (const event of session.run("Refactor the auth module.")) {
  if (event.type === "permission-request") {
    console.log(`[allowed ${event.name}]`, event.options.map((o) => o.label));
  }
}

Answering requests yourself (session.respond, an onPermission handler) arrives with a later release; today session.supports("respond") is false everywhere.

Next steps

On this page