Skip to content
Français

Continue a conversation

Resume an agent’s saved context or start a separate conversation from it.

Call result.resume() to send a follow-up request to the conversation created by a dispatch. The saved context includes the earlier messages, so the agent can continue from its previous work.

import { reportValue } from "./reporter.ts";
import { dispatch } from "@elie-laloum/outpost";
import { coder, repository, sandboxProvider } from "./outpost.config.ts";

const first = await dispatch({
  repository,
  sandboxProvider,
  agent: coder,
  brief: { text: "Inspect the parser and explain its edge cases." },
});
const next = await first.resume({
  brief: { text: "Which edge case deserves a regression test first?" },
});
reportValue(next.text);
// Example output: Add a regression test for empty parser input.

The follow-up runs in a fresh sandbox with the same repository, provider and branch settings. Outpost restores the saved conversation before starting the agent. You can override these settings in the resume() request.

result.conversation holds the conversation ID. To resume from another script, pass continuation: { id } to dispatch(). Outpost finds it in the agent’s store on this host or, once archived through a transport, on any machine.

Use result.fork() to explore another approach from the same saved context. It starts a separate conversation and leaves the original unchanged. Give the fork its own branch when its commits need to stay separate.

import { reportValue } from "./reporter.ts";
import { dispatch } from "@elie-laloum/outpost";
import { coder, repository, sandboxProvider } from "./outpost.config.ts";

const first = await dispatch({
  repository,
  sandboxProvider,
  agent: coder,
  brief: { text: "Inspect the parser and explain its edge cases." },
});
const alternative = await first.fork({
  branch: { mode: "named", name: "outpost/parser-state-machine" },
  brief: { text: "Rewrite the parser as a state machine and commit it." },
});
reportValue(alternative.conversation, alternative.branch);
// Example output: session-2 outpost/parser-state-machine

From an ID, continuation: { id, fork: true } does the same.

In a sandbox session, result.resume() and result.fork() continue in the same sandbox, with no restore. They take only brief and turn options: the sandbox settings are fixed.

import { createSandbox } from "@elie-laloum/outpost";
import { coder, repository, sandboxProvider } from "./outpost.config.ts";

await using sandbox = await createSandbox({
  repository,
  sandboxProvider,
  agent: coder,
});
const plan = await sandbox.dispatch({
  brief: { text: "Propose a fix for the flaky login test. Do not edit files." },
});
const tests = await sandbox.command({ executable: "npm", arguments: ["test"] });
await plan.resume({
  brief: { text: `Apply your fix. Current test output:\n${tests.stdout}` },
});

sandbox.resume(id, options) and sandbox.fork(id, options) take an ID instead, including one captured by an earlier dispatch.

Cold means a new sandbox (dispatch(), result.resume() on a dispatch() result); warm means the same open sandbox. Choose an agent compares the other capabilities.

AgentCold resumeWarm resumeFork
Claude Code, Codex, KimiYesYesYes
GitHub Copilot CLIYesYesNo
Built-in harnessYesYesYes
AntigravityNoSame sandbox onlyNo

After each turn, Outpost copies the conversation from the sandbox to the host. result.transcript holds the path of that copy.

AgentDefault storeHost location
Claude CodecreateClaudeConversations()~/.claude/projects/<project>/<id>.jsonl
CodexcreateCodexConversations()~/.codex/sessions/<yyyy>/<mm>/<dd>/
Copilot CLIcreateCopilotConversations().outpost/conversations/copilot/<id>.json
Kimi CodecreateKimiConversations().outpost/conversations/kimi/<id>.json
Built-in harnesscreateHarnessConversations().outpost/conversations/harness/<id>.jsonl

Copilot and Kimi keep a session as a directory: Outpost packs it into one JSON bundle. The conversationHome option of dispatch() or createSandbox() replaces ~, or the repository for bundles, as the root of these paths.

Restoring rewrites the repository paths recorded in the conversation to those of the new sandbox. To give a CLI you add its own store, see Native conversation formats.

createTransportConversations() wraps an agent’s store and also archives each capture through a transport. A conversation then resumes on another machine, or after the repository’s .outpost directory is deleted.

import {
  createAgent,
  createCodexConversations,
  createCodexHarness,
  createLocalTransport,
  createTransportConversations,
} from "@elie-laloum/outpost";

const conversations = createTransportConversations(createCodexConversations(), {
  transporter: createLocalTransport({ directory: "/mnt/shared/outpost" }),
  namespace: "my-project",
});

export const coder = createAgent({
  harness: createCodexHarness({ authentication: "account", conversations }),
});
  • Matching formatWrap the store of the same agent, such as createHarnessConversations() for createHarness(). A mismatch fails when the harness is created.
  • Stable namespaceUse one project name on every machine that shares these conversations.
  • Shared transportUse S3 or R2 between hosts; a local transport coordinates writers on one machine only.

result.transcriptReference identifies the archived copy. The Claude Code, Codex, Copilot and Kimi presets and createHarness() accept conversations.

saveConversations: false on Claude Code or Codex keeps conversations inside the sandbox: only a warm resume can continue them. conversations: false on createHarness() saves no transcript and rejects resume, fork and response repairs. Copilot and Kimi always capture.

import { createAgent, createClaudeHarness } from "@elie-laloum/outpost";

export const reviewer = createAgent({
  harness: createClaudeHarness({
    authentication: "account",
    saveConversations: false,
  }),
});
  • Bundle size: A Copilot or Kimi session is limited to 64 MiB and 4,096 files. Symlinks, missing required files and files changing during capture fail with code session.
  • Kimi state: Capture leaves out logs, background tasks, cron jobs, notifications and lock files. A resumed session restores the conversation, not running processes or schedules.
  • Antigravity: Nothing is captured, so it rejects the conversations option.
  • No encryption: Conversations hold prompts, repository content and tool output, stored and archived without encryption or authentication. Restrict access as you would to the repository.
  • Credentials apart: A conversation carries no credentials. The resuming agent needs its own authentication, and deleting credentials leaves conversations in place.
  • Host execution: With host execution, agents use your own session stores. Kimi refuses to restore a session already there under another workspace.
  • Fallback agents: A fallback agent takes no continuation. result.resume() continues with the candidate that answered.

API: DispatchResult · WarmDispatchResult · Sandbox · ConversationStore · createTransportConversations · createKimiConversations · createHarnessConversations.

Model routing records each effective selection in version-2 transcripts while retaining the harness storage format. Version-1 transcripts remain readable and are upgraded when routing is enabled on continuation. Resume and fork restore messages; the next step evaluates the router again without replaying completed model or tool calls. Journal replay emits recorded selections without contacting Jev or Laya.