Skip to content

Using the SDK

@robota-sdk/agent-sdk is the provider-neutral assembly layer that composes agent-core, agent-tools, agent-sessions, runtime services, commands, context loading, and transports into a cohesive experience. It exposes InteractiveSession as the primary entry point and createQuery() as the one-shot convenience API. Consumers create the provider instance and pass it in.

InteractiveSession — Primary Entry Point

InteractiveSession is the primary entry point for any interactive use case — CLI, web front-end, API server, or dynamic worker. It wraps Session via composition and provides an event-driven, queue-aware API.

typescript
import { InteractiveSession } from '@robota-sdk/agent-sdk';
import { AnthropicProvider } from '@robota-sdk/agent-provider-anthropic';

const provider = new AnthropicProvider({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

const session = new InteractiveSession({
  cwd: process.cwd(),
  provider,
  permissionMode: 'default',
});

session.on('text_delta', (delta) => process.stdout.write(delta));

// Submit a prompt (queued automatically if a run is in progress)
await session.submit('Refactor the auth module');

// Abort the in-flight run (partial response saved as 'interrupted')
session.abort();

// Cancel the queued prompt without touching the in-flight run
session.cancelQueue();

Events

InteractiveSession emits typed events. Clients subscribe and translate them into framework-specific state:

EventPayloadWhen
text_deltastringStreaming text chunk from the model
tool_startToolStartPayloadTool invocation started
tool_endToolEndPayloadTool invocation completed
thinkingSessionStatusRun started, completed, aborted, or queued
context_updateContextStateToken usage updated
errorErrorRun failed

History: IHistoryEntry[]

InteractiveSession maintains a universal history as IHistoryEntry[]. Each entry represents either a chat message (user or assistant turn) or a session event (tool call, system event, etc.). This unified timeline is the source of truth for display and persistence.

typescript
import type { IHistoryEntry } from '@robota-sdk/agent-core';

// Retrieve the full history
const history: IHistoryEntry[] = session.getFullHistory();

IHistoryEntry has a category field: 'chat' entries carry role/content for the AI provider; 'event' entries carry typed metadata for display. When forwarding conversation context to an AI provider, the session filters to chat-only entries automatically — the provider never sees event entries.

Event types include: tool-start (individual tool execution began), tool-end (individual tool execution completed with result), tool-summary (aggregated summary at execution end), and skill-invocation (skill activated).

Command Discovery

The SDK owns CommandRegistry and the command sources used by clients:

  • BuiltinCommandSource — built-in slash commands: /help, /clear, /compact, /mode, /model, /cost, /context, /permissions, /memory, /rewind, /provider, /resume, /background, /rename, /plugin, /reload-plugins, /language, /reset, /exit
  • SkillCommandSource — project and user skills discovered from .agents/skills/, .claude/skills/, .claude/commands/, and ~/.robota/skills/
  • PluginCommandSource — commands contributed by loaded plugins

Clients such as the CLI compose these sources into a registry for autocomplete. InteractiveSession.listCommands() returns executable system commands for transports and direct command execution, while skill commands discovered through SkillCommandSource are executed with session.executeSkillCommand().

System Commands

SystemCommandExecutor is embedded inside InteractiveSession. Consumers access commands through session.executeCommand(name, args) and session.listCommands() — the executor is not independently exported.

Before each submitted prompt, the session checks whether the input matches a built-in system command. If it does, the command is executed directly (e.g., clearing history, switching model, running compaction) and no LLM call is made. Unrecognized inputs are forwarded to the underlying Session.run().

Transport adapters (HTTP, WS, MCP) use session.listCommands() to discover available commands and session.executeCommand() to execute them.

createQuery() — Convenience API

createQuery({ provider }) is a lightweight factory that builds a one-shot query function pre-configured for a specific provider. Use it when you want simple prompt-in/response-out calls but need to reuse a configured provider instance across multiple calls.

typescript
import { createQuery } from '@robota-sdk/agent-sdk';
import { AnthropicProvider } from '@robota-sdk/agent-provider-anthropic';

const provider = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY! });
const ask = createQuery({ provider });
const response = await ask('List all TypeScript files in this project');

One-Shot Usage

The simplest way to interact with Robota is to create a query function and call it with a prompt. createQuery() builds an InteractiveSession internally, loads settings and project context from the working directory, and cleans up after each prompt.

typescript
import { createQuery } from '@robota-sdk/agent-sdk';
import { AnthropicProvider } from '@robota-sdk/agent-provider-anthropic';

const provider = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY! });
const query = createQuery({ provider });

const response = await query('List all TypeScript files in this project');

Options

typescript
const query = createQuery({
  provider,
  cwd: '/path/to/project',
  permissionMode: 'acceptEdits',
  maxTurns: 10,
});

const response = await query('Refactor this function');

Configuration

Config is loaded from 6 settings-file layers. .robota/ is the primary configuration convention; .claude/ paths are supported as a Claude Code compatibility layer. Later layers override earlier ones:

  1. User global: ~/.robota/settings.json (lowest priority)
  2. User global (Claude Code compatible): ~/.claude/settings.json
  3. Project (primary): .robota/settings.json
  4. Project local: .robota/settings.local.json (gitignored)
  5. Project (Claude Code compatible): .claude/settings.json
  6. Project local (Claude Code compatible): .claude/settings.local.json (gitignored, highest priority)

The .claude/ paths take higher runtime priority so that Claude Code settings override .robota/ defaults.

json
{
  "currentProvider": "qwen",
  "providers": {
    "qwen": {
      "type": "qwen",
      "model": "qwen-plus",
      "apiKey": "$ENV:DASHSCOPE_API_KEY",
      "baseURL": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
    },
    "openai": {
      "type": "openai",
      "model": "supergemma4-26b-uncensored-v2",
      "apiKey": "lm-studio",
      "baseURL": "http://localhost:1234/v1"
    },
    "anthropic": {
      "type": "anthropic",
      "model": "claude-sonnet-4-6",
      "apiKey": "$ENV:ANTHROPIC_API_KEY"
    }
  },
  "defaultTrustLevel": "moderate",
  "permissions": {
    "allow": ["Read(*)", "Glob(*)", "Grep(*)"],
    "deny": ["Bash(rm -rf *)"]
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "",
        "hooks": [{ "type": "command", "command": "bash .hooks/log-tool.sh" }]
      }
    ]
  }
}

InteractiveSession loads these settings for permissions, hooks, project context, skills, and session behavior. Provider profile resolution is performed by the consumer shell before creating the SDK session; the CLI uses currentProvider and providers to construct the active provider instance, then passes that instance to InteractiveSession. Qwen Model Studio uses type: "qwen" plus the documented DashScope OpenAI-compatible baseURL; generic OpenAI-compatible endpoints use type: "openai" plus baseURL. The legacy single provider object remains supported by CLI/provider-settings compatibility code when no active profile is configured.

The $ENV: prefix resolves environment variables at load time.

Context Discovery

InteractiveSession walks up from the working directory to find project context during initialization:

  • AGENTS.md — Project-level agent instructions and rules
  • CLAUDE.md — Additional agent instructions (Claude Code compatible)
  • Compact Instructions — Extracted from CLAUDE.md for use during context compaction
typescript
const session = new InteractiveSession({
  cwd: '/path/to/project',
  provider,
});

Use bare: true when you need a session without AGENTS.md/CLAUDE.md loading or plugin discovery.

System Prompt

The SDK assembles the system prompt internally from loaded project context, tool descriptions, command descriptors, trust level, active task context, and optional appended instructions.

typescript
const session = new InteractiveSession({
  cwd: process.cwd(),
  provider,
  appendSystemPrompt: 'Prefer concise responses.',
});

Session Features

InteractiveSession provides these capabilities:

FeatureDescription
Permission enforcementTool calls are gated by the permission system
Hook executionPreToolUse/PostToolUse/PreCompact/PostCompact hooks fire automatically
Context trackingToken usage is tracked and available via getContextState()
Auto-compactionContext is compressed when usage exceeds ~83.5%
Session persistenceConversations can be saved/loaded via SessionStore. ISessionRecord includes history (IHistoryEntry[]) plus background task snapshots for restoration and debugging
Session resume/forkRestore a previous session with resumeSessionId or fork with forkSession. On resume, session.injectMessage() restores AI context from persisted history
Session naminggetName() / setName() for human-friendly session identification
Abortsession.abort() cancels via AbortSignal. Partial response committed as 'interrupted'
Universal historygetFullHistory() returns IHistoryEntry[] — the unified chat + event timeline
Background workSubagent jobs are tracked through runtime-owned task state, transcripts, and background task events
Replay eventsSession runs forward core provider/tool boundary events into append-only JSONL logs

Subagent Sessions

createSubagentSession() spawns a child session for delegating subtasks to a subagent. The child session forks the parent's context (context:fork), inherits hooks and permissions, and runs independently.

typescript
import { createSubagentSession } from '@robota-sdk/agent-sdk';

const subSession = createSubagentSession({
  parentSession: session,
  agentDefinition: 'explore', // built-in agent type
  prompt: 'Find all usages of the deprecated API',
});

const result = await subSession.run();

Agent Tool Batch Jobs

The model-visible Agent tool supports both the existing single-job shape and a batch jobs shape for explicit parallel requests:

typescript
{
  jobs: [
    { prompt: 'Review the API contract', subagent_type: 'Plan' },
    { prompt: 'Inspect implementation risks', subagent_type: 'Explore' },
  ],
}

When jobs is present, the Agent tool starts every valid job before waiting for results. The returned JSON includes success, groupId, agentIds, and ordered per-job results. This gives the runtime a deterministic path for requests such as "run two agents in parallel" even when the model emits only one tool call.

Tool Filtering

Subagent tool access is resolved in order: denylist (disallowedTools) is applied first, then allowlist (tools) filters to permitted tools only. The Agent tool is always removed from subagent sessions to prevent recursive spawning.

Model Shortcuts

Agent definitions accept model shortcuts that resolve to full model IDs: sonnet -> claude-sonnet-4-6, haiku -> claude-haiku-4-5, opus -> claude-opus-4-6.

Agent Definitions

Agent definitions describe reusable agent configurations. Built-in types:

TypeModelToolsDescription
General-purposeinheritall toolsFull tool access, inherits parent model
explorehaikuread-onlyLightweight codebase exploration
planinheritread-onlyMulti-step planning with read-only tools

Custom agent definitions can be placed in .robota/agents/ (primary) or .claude/agents/ (Claude Code compatible) and are loaded by AgentDefinitionLoader. See agent-sdk SPEC.md for the IAgentDefinition interface.

Agent Definition Schema

FieldTypeDescription
namestringAgent identifier
descriptionstringWhat the agent does
systemPromptstringAgent's system prompt (markdown body)
modelstringModel override (sonnet/haiku/opus or full ID)
maxTurnsnumberMax agentic turns
toolsstring[]Tool allowlist
disallowedToolsstring[]Tool denylist

Framework Suffixes

The SDK appends a framework suffix to the subagent's system prompt to shape its output format. Subagents receive a suffix requesting a concise report of findings. Fork workers receive a structured suffix with a 500-word limit.

Subagent Transcript

Subagent execution is logged to {logsDir}/{parentSessionId}/subagents/{agentId}.jsonl for debugging and audit purposes. Streaming text deltas are appended to this transcript while the provider request is still running. The parent session JSON stores the background task snapshot and transcript path; it does not rewrite the whole session file for every token chunk.

Replay-Grade Session Events

Session.run() now forwards core execution events through the session logger. Current events include provider request envelopes, normalized provider responses, assistant message commits, tool batch starts, tool execution requests, and tool execution results.

These events are append-only provenance for debugging and future /resume replay. Full deterministic replay still requires raw provider response/chunk storage, payload reference handling, redaction rules, history mutation events, and a replay validator.

Always-Streaming Policy

The Anthropic provider always uses the streaming API internally, even when no onTextDelta callback is provided. This avoids the 10-minute HTTP timeout that can occur with long-running tool loops on non-streaming requests. The final response text is assembled from the stream. See agent-provider-anthropic SPEC.md for details.

Output Token Limits

The Anthropic provider uses getModelMaxOutput() to determine the default max_tokens value per model rather than hardcoding a fixed limit. Current defaults: Sonnet 4.6 supports 64K output tokens, Opus 4.6 supports 128K output tokens. See agent-provider-anthropic SPEC.md for details.

Marketplace Client

MarketplaceClient manages plugin marketplace registries via git clones stored in ~/.robota/marketplaces/. It supports GitHub repositories, arbitrary git URLs, and local filesystem paths as marketplace sources. The CLI exposes this through /plugin marketplace add/remove/list/update commands. See agent-sdk SPEC.md for the full API.

Transport Adapters

InteractiveSession is the single entry point for all interactive use cases. Transport adapters in the agent-transport-* packages consume it to expose the session over different protocols:

PackageProtocolDescription
agent-transport-httpHTTP / RESTHono-based adapter; runs on Cloudflare Workers, Node.js, Lambda
agent-transport-mcpMCPExposes the session as an MCP server for Claude and other agents
agent-transport-wsWebSocketFramework-agnostic real-time adapter (any WS library)
agent-transport-headlessstdin/stdout (non-interactive)Non-interactive execution with text/json/stream-json output

Each transport wraps an InteractiveSession instance and translates protocol messages into submit() / abort() calls, then forwards emitted events back to the client. No separate gateway interface exists — InteractiveSession is the gateway.

All transport adapters implement the ITransportAdapter interface (exported from @robota-sdk/agent-sdk), which defines a common lifecycle: attach(session), start(), and stop(). Each package provides a factory function (e.g., createHttpTransport(), createWsTransport(), createMcpTransport(), createHeadlessTransport()) that returns an ITransportAdapter. createHeadlessTransport() also accepts a createHeadlessRunner() helper for pre-configured non-interactive execution.

agent-remote-client is a companion package that provides an HTTP client for calling an agent exposed via agent-transport-http. It has no dependency on agent-sdk.

Assembly vs Direct Usage

Use caseApproach
Quick one-shotcreateQuery({ provider }) — creates an InteractiveSession internally
Interactive CLI / web / serverInteractiveSession — event-driven, queuing, command handling
Expose over HTTP / MCP / WSagent-transport-{http,mcp,ws} wrapping InteractiveSession
Non-interactive / headlessagent-transport-headless — text, JSON, or stream-JSON output
Call a remote agent over HTTPagent-remote-client — standalone HTTP client
Custom agent (no SDK)new Robota() from agent-core directly
Custom session (no SDK)new Session() from agent-sessions with your own tools/provider

Released under the MIT License.