This document defines the long-lived SDK API shape for A3S Code. The goal is to keep the public SDK stable while the runtime, harness integrations, and tool implementations continue to evolve.
- Keep the kernel small: sessions run prompts, stream events, execute selected tools, record evidence, and expose state.
- Keep extension policy outside the kernel: AHP harnesses, host UIs, and callers own background advice, context supplements, and proposed programmatic actions.
- Prefer object-shaped APIs for anything that can grow.
- Keep public method names short. Prefer one-word verbs (
send,stream,task,tasks,git) when the receiver already provides the domain. - Preserve compatibility by adding new stable entry points before deprecating old shortcuts.
- Keep raw JSON at system boundaries only; expose typed options and typed snapshots everywhere SDK users build product logic.
Agent owns configuration and creates sessions.
Stable calls:
Agent.create(config_source)
Agent.session(workspace, options?)
Agent.resume_session(session_id, options)
Agent.session_for_agent(workspace, agent_name, agent_dirs?, options?)
Agent.session_for_worker(workspace, worker_spec, options?)
Rules:
session(...)remains the default entry point.- Worker/subagent setup is data-driven with
WorkerAgentSpec; callers should not create temporary agent files for ephemeral workers. - Model, memory, session store, security, queue, AHP, MCP, and worker choices are
typed objects in
SessionOptions, not magic backend strings.
AgentSession / Session is the primary runtime handle.
Stable calls:
send(prompt | { prompt, history?, attachments? }, history?)
run(prompt | { prompt, history?, attachments? }, history?)
stream(prompt | { prompt, history?, attachments? }, history?)
history()
close()/cancel()
Rules:
sendandstreamremain prompt-first because prompt is the dominant input.- Any future optional argument must be added through the request object, not a new positional parameter.
send_request,stream_request, and attachment-specific methods remain compatibility helpers; new examples should usesend({ ... })andstream({ ... }).- Supplying explicit history keeps the operation isolated from session history.
Direct calls bypass the LLM and are for deterministic product workflows.
Stable calls:
tool(name, args)
program(options)
task(options)
tasks(tasks)
git(options)
web_search(options)
read_file(path)
bash(command)
grep(pattern)
glob(pattern)
Rules:
tool(name, args)is the raw escape hatch.program,task,tasks,git,web_search, and MCP APIs are object-shaped because their schemas can grow.- Simple scalar helpers (
read_file,bash,grep,glob) may stay scalar as convenience wrappers; richer variants should be added as object-shaped methods instead of widening the scalar signatures. - Programmatic Tool Calling scripts are never auto-executed from harness advice;
callers explicitly run them through
program(...)so permissions, confirmations, and trace recording remain active.
Product UIs should build from replayable state rather than parsing text.
Stable calls:
runs()
run_snapshot(run_id)
run_events(run_id)
current_run()
active_tools()
trace_events()
verification_reports()
verification_summary()
verification_summary_text()
pending_confirmations()
confirm_tool_use(tool_id, approved, reason?)
Rules:
- Run snapshots and event records are durable data contracts.
- Active tool snapshots are live state for UX only; run events remain the audit source of truth.
- Verification reports are explicit evidence and should not be inferred from the final answer text.
Live extensions mutate session capabilities while keeping one execution path.
Stable calls:
add_mcp(config)
remove_mcp(name)
mcps()
register_agent_dir(path)
register_worker_agent(worker_spec)
register_worker_agents(worker_specs)
register_hook(name, event_type, handler, matcher?, config?)
unregister_hook(hook_id)
Rules:
- Prefer
add_mcp(config)over positional MCP overloads. - MCP tools join the normal tool registry and go through the same selection, permission, confirmation, trace, and AHP hook paths as built-in tools.
- Hooks and AHP supervise the existing agent loop; they do not create a second in-core advisor runtime.
- Rust: snake_case methods and Rust structs.
- Python: snake_case methods, Python dictionaries for extension payloads, typed classes for durable option providers.
- Node.js: camelCase methods and typed option objects.
- Event
typevalues stay snake_case because they are serialized runtime data. - Public methods should be as short as clarity allows. If the receiver already
names the domain, avoid repeating it (
session.git(...), notsession.git_command(...);session.add_mcp(...), notsession.add_mcp_server_config(...)).
- Add object-shaped replacements before removing positional overloads.
- Keep old overloads documented as compatibility paths only.
- Do not reuse a method name with incompatible semantics.
- Do not expose a background runtime concept that duplicates AHP or caller-owned harness behavior.
- Do not add model-visible shortcuts that bypass
task,parallel_task,program, permissions, confirmations, or trace recording.
Prefer this shape for new public calls:
await session.send({ prompt: 'Explain auth', history, attachments })
await session.git({ command: 'worktree', subcommand: 'list' })
await session.addMcp({
name: 'github',
transport: { type: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-github'] },
timeoutMs: 30000,
})
await session.program({ source, inputs, allowedTools, limits })
await session.task({ agent: 'explore', description: 'Find auth', prompt: 'Summarize auth files.' })Avoid this shape for new calls:
await session.sendWithAttachments('Explain auth', attachments, history)
await session.git('worktree', 'list', null, null, true, null, false, null, null, false)
await session.addMcpServer('github', 'stdio', 'npx', ['-y', '@modelcontextprotocol/server-github'])The positional forms may remain for compatibility, but new SDK examples should use object-shaped methods.