diff --git a/.github/assets/architecture.svg b/.github/assets/architecture.svg
new file mode 100644
index 0000000..2e00cf0
--- /dev/null
+++ b/.github/assets/architecture.svg
@@ -0,0 +1,220 @@
+
diff --git a/.github/assets/event-flow.svg b/.github/assets/event-flow.svg
new file mode 100644
index 0000000..1e6297b
--- /dev/null
+++ b/.github/assets/event-flow.svg
@@ -0,0 +1,106 @@
+
diff --git a/.github/assets/features.svg b/.github/assets/features.svg
new file mode 100644
index 0000000..87eee14
--- /dev/null
+++ b/.github/assets/features.svg
@@ -0,0 +1,66 @@
+
diff --git a/.github/assets/hero-banner.svg b/.github/assets/hero-banner.svg
new file mode 100644
index 0000000..ca27a1e
--- /dev/null
+++ b/.github/assets/hero-banner.svg
@@ -0,0 +1,131 @@
+
diff --git a/.github/assets/quick-start-header.svg b/.github/assets/quick-start-header.svg
new file mode 100644
index 0000000..1503345
--- /dev/null
+++ b/.github/assets/quick-start-header.svg
@@ -0,0 +1,21 @@
+
diff --git a/.github/assets/why-different.svg b/.github/assets/why-different.svg
new file mode 100644
index 0000000..e33741e
--- /dev/null
+++ b/.github/assets/why-different.svg
@@ -0,0 +1,82 @@
+
diff --git a/README.md b/README.md
index e8cb483..a6fdf07 100644
--- a/README.md
+++ b/README.md
@@ -1,449 +1,520 @@
-# General Agent SDK
+
-`general-agent-sdk` is a session-first embedded SDK that extracts the agent execution kernel from OpenClaw and exposes it as a host-controlled TypeScript package.
+
+
+
+
+
-The SDK is intentionally narrow: it preserves execution-layer semantics such as tool calls, hosted-tool suspend/resume, compaction, plugin policy, and provider-specific streaming, while leaving orchestration, channel routing, profile ownership, and canonical session state to the host application.
+
-## Status
+[](https://www.npmjs.com/package/general-agent-sdk)
+
+[](https://www.typescriptlang.org/)
+
+[](./LICENSE)
+
+[](./tests)
+
+[](https://nodejs.org/)
-- Repository: `https://github.com/babelcloud/general-agent-sdk`
-- Package name: `general-agent-sdk`
-- Current package version: `0.1.0`
-- Runtime: Node.js `>=22.14.0`
-- Module format: ESM
-- CI workflow: [`.github/workflows/sdk-ci.yml`](./.github/workflows/sdk-ci.yml)
+
-This repository is currently host-oriented and private by default. It is designed to be consumed as a pinned dependency or submodule by a parent host application.
+**The TypeScript SDK for building AI agents that call tools, manage sessions, and ship to production.**
-## Breaking Changes
+[Quick Start](#-get-started-in-60-seconds) Β· [Architecture](#-architecture) Β· [API Reference](./SDK%20DOCS/API-REFERENCE.md) Β· [Examples](./SDK%20DOCS/)
-The current General Agent SDK surface intentionally removes earlier transitional names and compatibility entrypoints.
+
-- Root factory/type names are now `createGeneralAgentSdk`, `GeneralAgentSdk`, `GeneralAgentSdkOptions`, and `GeneralAgentSession`.
-- The package no longer ships the `./compat/visionclaw` entrypoint.
-- The package no longer ships the `./plugin-sdk` alias.
+
-If you are upgrading from an earlier internal prototype, update root imports and switch any host integration that depended on removed subpaths to the native SDK session/event APIs.
+
-## What This SDK Is
+## Why General Agent SDK?
-- A standalone embedded agent kernel extracted from OpenClaw
-- A session factory plus session objects
-- A bridge that preserves structured execution semantics instead of flattening everything into text
-- A host-integrated runtime that writes all state and logs under host-owned roots
+Most agent frameworks give you **wrappers around chat completions** β you manage the tool loop, you track the state, you handle restarts. General Agent SDK gives you a **complete execution kernel**:
-## What This SDK Is Not
+
+
-- Not the full OpenClaw gateway
-- Not a replacement for a host application's outer runtime loop
-- Not a second authoritative session registry
-- Not a channel manager, cron daemon, control plane, or desktop automation environment
+
-## Design Principles
+
+
-- **Session-first API**: the host bootstraps the SDK once, then creates and reuses sessions explicitly
-- **Host-owned persistence**: the host decides where session files, state files, and raw event logs live
-- **Execution fidelity**: tool-call identity, hosted-tool resume boundaries, and tool-result ordering are preserved
-- **Failure containment**: the SDK stays behind an engine-gated loader path in the host
-- **Traceability**: extracted upstream files are tracked through a provenance manifest and verification scripts
+> **The SDK runs the agent loop for you.** You send a message, the agent autonomously calls tools, reasons about results, calls more tools, and streams every event back β until it's done or needs your input.
-## Host / SDK Boundary
+
-### SDK responsibilities
+
-- Create and reuse agent sessions
-- Stream assistant, reasoning, tool, hosted-tool, compaction, and usage events
-- Preserve `tool_call`, `tool_result`, and `tool_error` semantics
-- Resolve embedded provider/auth/plugin/tool behavior
-- Start and stop registered stdio MCP runtimes for active runs
-- Emit canonical host-facing logs and optional raw stream events
+
-### Host responsibilities
+
-- Profile roots and workspace roots
-- Credentials and environment variables
-- Canonical session metadata
-- Channel ingress and egress
-- Cross-engine continuity and owner-facing orchestration
-- Which MCP servers are registered and enabled for a session
+
-This separation is intentional. The SDK does not introduce a new top-level runtime abstraction above the host.
+
-## Public API
+
-The supported API surface is exported from [`src/index.ts`](./src/index.ts) and backed by the files under [`src/public/`](./src/public).
+
-const sdk = await createGeneralAgentSdk({
- workspaceDir,
- stateDir,
- agentDir,
- profileId: "default",
- pluginMode: "disabled",
- logger,
- sessionStore,
- hostedTools,
- env: process.env,
- tools: {
- web: {
- fetch: {
- firecrawl: {
- apiKey: process.env.FIRECRAWL_API_KEY,
- },
- },
- search: {
- apiKey: process.env.BRAVE_SEARCH_API_KEY,
- },
- },
- },
-});
+### Step 1 β Install
+
+```bash
+npm install general-agent-sdk
```
-### Session creation
+### Step 2 β Set your API key
-```ts
-const session = sdk.createSession({
- identity: {
- mode: "general",
- sessionId: "sess-general",
- sessionKey: "host:default:general",
- },
- systemPrompt: "Use the finish tool immediately.",
- modelRef: "openai/gpt-5.4",
- sessionFile,
- authProfileId: "enterprise-default",
- rawEventLogPath,
-});
+```bash
+export ANTHROPIC_API_KEY="sk-ant-..."
+
+# Optional: use a custom endpoint
+# export ANTHROPIC_BASE_URL="https://your-proxy.example.com"
```
-### Session lifecycle
+### Step 3 β Run your first agent
-The SDK can enumerate stored sessions, reopen them by `sessionId`, continue a known identity, fork a stored transcript into a new session, and read persisted transcript history.
+```typescript
+import { createGeneralAgentSdk } from "general-agent-sdk";
+import { randomUUID } from "node:crypto";
+import path from "node:path";
+import os from "node:os";
-```ts
-const sessions = await sdk.listSessions();
-const resumed = await sdk.resumeSession("sess-general");
-const continued = await sdk.continueSession({
- identity: {
- mode: "general",
- sessionId: "sess-general",
- sessionKey: "host:default:general",
- },
-});
-const forked = await sdk.forkSession("sess-general", {
- identity: {
- mode: "general",
- sessionId: "sess-general-fork",
- sessionKey: "host:default:general-fork",
+// 1. Initialize
+const sdk = await createGeneralAgentSdk({
+ workspaceDir: process.cwd(),
+ stateDir: path.join(process.cwd(), ".agent-state"),
+ agentDir: path.join(process.cwd(), ".agent"),
+ profileId: "default",
+ pluginMode: "disabled",
+ logger: { onDebug() {}, onInfo() {}, onWarn() {}, onError() {} },
+ sessionStore: {
+ async load() { return null; },
+ async save() {},
+ async resolveSessionFile(id) {
+ return path.join(os.tmpdir(), `${id.sessionId}.jsonl`);
+ },
},
- sessionFile: forkSessionFile,
});
-const history = await sdk.readSessionHistory("sess-general");
-```
-### Turn streaming
+// 2. Create a session
+const session = sdk.createSession({
+ identity: { mode: "general", sessionId: randomUUID(), sessionKey: "demo" },
+ systemPrompt: "You are a helpful assistant. Use tools when needed.",
+ modelRef: "claude-sonnet-4-20250514",
+ sessionFile: path.join(os.tmpdir(), "demo-session.jsonl"),
+});
-```ts
+// 3. Stream a turn β the agent calls tools autonomously
for await (const event of session.streamTurn({
role: "user",
- content: [{ type: "text", text: "finish now" }],
+ content: [{ type: "text", text: "List the files in the current directory" }],
})) {
- // host consumes normalized GeneralAgentStreamEvent values
+ switch (event.kind) {
+ case "assistant_delta": process.stdout.write(event.text); break;
+ case "tool_call": console.log(`\nπ§ ${event.toolName}`); break;
+ case "tool_result": console.log(` β done`); break;
+ case "turn_complete": console.log(`\n\nπ Turn complete (${event.stopReason})`); break;
+ }
}
+
+await sdk.shutdown();
```
-### Hosted-tool resume
+> **That's it.** The agent autonomously reads the directory, reasons about the output, and streams a formatted answer β all in one `for await` loop.
-When the SDK emits a hosted-tool call, the host must execute the hosted tool and resume the same session with the same `callId`.
+
-```ts
-for await (const event of session.submitHostedToolResult({
- callId,
- output: { ok: true },
-})) {
- // resumed stream continues with the same execution context
-}
-```
+---
-Hosted tools currently force sequential tool execution inside the vendored loop. That keeps same-run suspend/resume robust for hosted tools such as `finish`.
+
-Across SDK recreation, the runtime can recover both single-tool and multi-tool hosted-tool suspensions. When the assistant issues multiple tool calls and one is a hosted tool, the SDK snapshots the full context and resumes correctly after restart.
+## π― Core Concepts
-### Hooks
+### The Event Stream
-The SDK now exposes an OpenClaw-aligned hook surface for embedded-agent flows. Runtime-managed hooks currently include pre-run model/prompt hooks, `llm_input`, `agent_end`, `llm_output`, tool hooks, transcript persist hooks, and session lifecycle hooks. Host-bridged hooks such as `message_sending`, `message_sent`, `message_received`, `inbound_claim`, `before_dispatch`, `gateway_start`, and `gateway_stop` can be emitted directly through the SDK.
+Every turn returns an `AsyncIterable`. No callbacks, no observers β one loop handles everything:
-```ts
-const result = await sdk.emitHook({
- hookName: "message_sending",
- event: {
- to: "channel:123",
- content: "hello",
- },
- context: {
- channelId: "discord",
- },
-});
-```
+
+
-The public hook registry accepts the full `GeneralAgentHookRegistration` union, including:
-
-- `before_model_resolve`
-- `before_prompt_build`
-- `before_agent_start`
-- `llm_input`
-- `llm_output`
-- `agent_end`
-- `before_compaction`
-- `after_compaction`
-- `before_reset`
-- `inbound_claim`
-- `message_received`
-- `message_sending`
-- `message_sent`
-- `before_tool_call`
-- `after_tool_call`
-- `tool_result_persist`
-- `before_message_write`
-- `session_start`
-- `session_end`
-- `subagent_spawning`
-- `subagent_delivery_target`
-- `subagent_spawned`
-- `subagent_ended`
-- `gateway_start`
-- `gateway_stop`
-- `before_dispatch`
-
-All SDK-native hooks listed above are now auto-emitted by the runtime at the appropriate lifecycle points. This includes `before_reset`, compaction hooks (`before_compaction` / `after_compaction`), and subagent lifecycle hooks (`subagent_spawning` / `subagent_delivery_target` / `subagent_spawned` / `subagent_ended`). Host-bridged hooks such as `gateway_start`, `gateway_stop`, `inbound_claim`, `message_received`, `message_sending`, `message_sent`, and `before_dispatch` remain available through the `sdk.emitHook(...)` dispatch path.
-
-### Dynamic MCP servers
-
-The session can register dynamic MCP servers. The current runtime supports local `stdio` MCP servers and injects their tools into the same vendored loop as built-ins and hosted tools.
-
-```ts
-session.setDynamicMcpServers({
- echo_server: {
- transport: "stdio",
- command: process.execPath,
- args: ["/abs/path/to/echo-server.mjs"],
- },
-});
+
+
+
+
-const query = session.getCurrentQuery();
-const status = await query?.mcpServerStatus?.();
-await query?.toggleMcpServer?.("echo_server", false);
+```typescript
+for await (const event of session.streamTurn(input)) {
+ switch (event.kind) {
+ case "assistant_delta": // β streaming text from the model
+ case "reasoning_delta": // β model thinking (extended thinking)
+ case "tool_call": // β built-in tool invoked
+ case "tool_result": // β tool returned a result
+ case "hosted_tool_call": // β YOUR tool was requested β SDK suspends βΈοΈ
+ case "usage_snapshot": // β token usage update
+ case "turn_complete": // β this turn is done β
+ }
+}
```
-Both MCP transport modes are supported:
+---
-- `stdio`: local process servers
-- `http`: remote HTTP-based MCP endpoints
+### π― Hosted Tools β Your Code, The Model's Brain
-Example with `http` transport:
+Define tools the AI can call. You implement the logic; the SDK orchestrates the lifecycle:
-```ts
-session.setDynamicMcpServers({
- remote_server: {
- transport: "http",
- url: "https://mcp.example.com/api",
- headers: { Authorization: "Bearer token" },
- },
+```typescript
+const sdk = await createGeneralAgentSdk({
+ // ...
+ hostedTools: [{
+ name: "get_weather",
+ description: "Get current weather for a city",
+ inputSchema: {
+ type: "object",
+ properties: { city: { type: "string" } },
+ required: ["city"],
+ },
+ }],
});
+
+for await (const event of session.streamTurn(userMsg)) {
+ if (event.kind === "hosted_tool_call") {
+ // SDK suspends automatically βΈοΈ
+ const weather = await getWeather(event.input.city);
+
+ // Resume with your result βΆοΈ
+ for await (const e of session.submitHostedToolResult({
+ callId: event.callId,
+ output: weather,
+ })) {
+ if (e.kind === "assistant_delta") process.stdout.write(e.text);
+ }
+ break;
+ }
+}
```
-### Session reset
+> **Restart-safe:** Hosted tool pauses survive process restarts. The SDK snapshots context and resumes correctly β even with multi-tool parallel calls.
+
+---
+
+### π¬ Multi-Turn Memory
-A session can be reset to clear its message history, usage state, and pending hosted-tool state while preserving the session identity and configuration. This is useful when the host wants to start fresh within the same session without creating a new one.
+Sessions automatically maintain conversation history:
-```ts
-await session.reset("context_overflow");
+```typescript
+// Turn 1
+for await (const e of session.streamTurn({
+ role: "user",
+ content: [{ type: "text", text: "My name is Alice. I'm building a TypeScript app." }],
+})) { /* ... */ }
+
+// Turn 2 β the agent remembers everything
+for await (const e of session.streamTurn({
+ role: "user",
+ content: [{ type: "text", text: "What's my name and what am I building?" }],
+})) { /* ... */ }
+// β "Your name is Alice and you're building a TypeScript app."
```
-The reset fires a `before_reset` hook before clearing state, allowing hooks to observe the outgoing transcript.
+---
-### Compaction
+### πͺ Hooks β Intercept Everything
-The SDK supports runtime compaction to manage context window pressure. Compaction can be triggered manually or automatically based on token usage thresholds.
+26 hooks let you observe, modify, or block any lifecycle event:
-```ts
-// Manual compaction
-await session.requestCompaction();
+```typescript
+const sdk = await createGeneralAgentSdk({
+ hooks: [
+ // π Dynamic model routing
+ {
+ pluginId: "my-app",
+ hookName: "before_model_resolve",
+ handler: (ev) => ({
+ modelOverride: needsPower(ev) ? "claude-opus-4-20250514" : "claude-sonnet-4-20250514",
+ }),
+ },
-// Automatic compaction when usage exceeds threshold
-await session.maybeCompactByTokens({
- usedPctThreshold: 85, // compact when context is 85% full
- cooldownMs: 60_000, // minimum 60s between compactions
+ // π‘οΈ Safety guardrails
+ {
+ pluginId: "my-app",
+ hookName: "before_tool_call",
+ handler: (ev) => {
+ if (ev.toolName === "exec" && ev.params.command?.includes("rm -rf"))
+ return { block: true, blockReason: "Dangerous command blocked" };
+ },
+ },
+
+ // π Usage audit trail
+ {
+ pluginId: "my-app",
+ hookName: "llm_output",
+ handler: (ev) => {
+ db.insert({ model: ev.model, tokens: ev.usage?.input + ev.usage?.output });
+ },
+ },
+ ],
});
```
-Compaction truncates older messages and replaces them with a concise summary, keeping the most recent conversation context intact. The SDK emits `compaction_started` and `compaction_finished` stream events and fires `before_compaction` / `after_compaction` hooks during the process.
-
-The context window size is resolved dynamically based on the model (e.g., 200K for Claude models, 128K for GPT-4o, 1M+ for Gemini models).
-
-### Subagents
+
+π Full hook reference (19 SDK-native + 7 host-bridged)
+
+
+
+**SDK-native hooks** β auto-fired by the runtime:
+
+| Hook | Modifiable | Fires when... |
+|:-----|:---:|:---|
+| `before_model_resolve` | β | Model selection begins |
+| `before_prompt_build` | β | System prompt is being assembled |
+| `before_agent_start` | β | Agent run is about to begin |
+| `llm_input` | β | Request sent to LLM |
+| `llm_output` | β | Response received from LLM |
+| `agent_end` | β | Agent run completed |
+| `before_tool_call` | β | Tool is about to execute |
+| `after_tool_call` | β | Tool execution finished |
+| `tool_result_persist` | β | Tool result being saved to transcript |
+| `before_message_write` | β | Message being written to history |
+| `session_start` | β | Session first activated |
+| `session_end` | β | Session completed |
+| `before_compaction` | β | Context compaction starting |
+| `after_compaction` | β | Context compaction finished |
+| `before_reset` | β | Session about to clear |
+| `subagent_spawning` | β | Child agent creation requested |
+| `subagent_delivery_target` | β | Routing child agent delivery |
+| `subagent_spawned` | β | Child agent created |
+| `subagent_ended` | β | Child agent finished |
+
+**Host-bridged hooks** β you trigger these via `sdk.emitHook()`:
+
+| Hook | Purpose |
+|:-----|:--------|
+| `inbound_claim` | Incoming message routing |
+| `before_dispatch` | Pre-dispatch filtering |
+| `message_received` | Message arrival notification |
+| `message_sending` | Modify/cancel outgoing messages |
+| `message_sent` | Delivery confirmation |
+| `gateway_start` | Gateway lifecycle start |
+| `gateway_stop` | Gateway shutdown |
+
+
+
+---
+
+### π MCP Integration
+
+Plug in any [Model Context Protocol](https://modelcontextprotocol.io/) server β tools appear alongside built-ins:
+
+```typescript
+session.setDynamicMcpServers({
+ // Local process (stdio)
+ filesystem: {
+ transport: "stdio",
+ command: "npx",
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"],
+ },
-The `subagents` tool is a first-class core built-in. When the agent calls it, the SDK automatically creates a child `GeneralAgentSdkSession` with:
+ // Remote endpoint (HTTP)
+ my_api: {
+ transport: "http",
+ url: "https://mcp.example.com/api",
+ headers: { Authorization: "Bearer token" },
+ },
+});
+```
-- **Independent message history** β the child session has its own transcript, isolated from the parent
-- **Scoped instructions** β the child receives its own system prompt via the `instructions` parameter
-- **Scoped tool access** β the child inherits the parent's tools except `subagents` itself (preventing infinite recursion). An optional `allowedTools` parameter further restricts the child's tool set.
-- **Parent/child coordination** β the parent's agent loop blocks while the child runs to completion, then receives the child's output as the tool result
+---
-All 4 subagent lifecycle hooks fire automatically:
-- `subagent_spawning` β before creation (can block with `{ status: "error" }`)
-- `subagent_delivery_target` β after creation, before execution
-- `subagent_spawned` β after child session is ready
-- `subagent_ended` β after child completes (with `outcome: "ok"` or `"error"`)
+### π€ Subagents
-### File checkpoints
+The agent can spawn scoped child agents to divide and conquer complex tasks:
-File mutation tools automatically create SDK-managed checkpoints before successful `write`, `edit`, and `apply_patch` calls. Checkpoints are Git-independent and can be rewound through the session API.
+```typescript
+const session = sdk.createSession({
+ systemPrompt: `You are a tech lead. Delegate tasks using the subagents tool.`,
+ // ...
+});
-```ts
-const checkpoints = await session.listCheckpoints();
-await session.restoreCheckpoint(checkpoints[0]!.id);
+// The agent will autonomously:
+// 1. Analyze the task
+// 2. Spawn child agents with scoped instructions + tools
+// 3. Collect results from each child
+// 4. Synthesize a final answer
```
-Restoring a checkpoint rewinds that checkpoint and any newer checkpoints, so rollback stays linear and predictable.
+Each child gets **independent message history** and **scoped tool access**. The `subagents` tool is excluded from children to prevent infinite recursion. Four lifecycle hooks fire automatically: `subagent_spawning` β `subagent_spawned` β `subagent_ended`.
-## Event Model
+---
-`GeneralAgentStreamEvent` currently supports:
+### π Session Management
-- `assistant_delta`
-- `reasoning_delta`
-- `reasoning_end`
-- `tool_call`
-- `tool_result`
-- `tool_error`
-- `hosted_tool_call`
-- `usage_snapshot`
-- `compaction_started`
-- `compaction_finished`
-- `turn_complete`
+```typescript
+const session = sdk.createSession({ ... }); // Create
+const resumed = await sdk.resumeSession("sess-123"); // Resume
+const forked = await sdk.forkSession("sess-123", { // Fork
+ identity: { ... },
+});
+const sessions = await sdk.listSessions(); // List all
+const history = await sdk.readSessionHistory("id"); // Read transcript
+await session.reset("context_overflow"); // Reset
+const usage = session.getUsageSnapshot(); // Token usage
+```
-The host is expected to normalize these events into its own runtime contract when necessary.
+**Context Compaction** β long conversations don't overflow:
-## Persistence Model
+```typescript
+await session.maybeCompactByTokens({
+ usedPctThreshold: 85, // trigger at 85% context usage
+ cooldownMs: 60_000, // min 60s between compactions
+});
+```
-The SDK does not own canonical session identity. Instead, the host provides a `sessionStore` adapter and resolves the session file path explicitly.
+**File Checkpoints** β every write creates an automatic rollback point:
-Key persistence properties:
+```typescript
+const checkpoints = await session.listCheckpoints();
+await session.restoreCheckpoint(checkpoints[0].id);
+```
-- provider-specific transcripts are allowed
-- provider-specific raw stream logs are allowed
-- both must remain under host-owned directories
-- session identity must come from the host
-- no parallel SDK-owned global session registry is introduced
-- pending hosted-tool wait states and reconstructible continuation snapshots may be persisted when the runtime can resume them safely
+
-The persistence adapter lives in [`src/public/persistence.ts`](./src/public/persistence.ts).
+---
-## Logging Model
+
-The SDK emits canonical host-facing log events through `GeneralAgentHostLogger`.
+## π Architecture
-Supported log categories:
+
+
-- `system_prompt`
-- `tool_call`
-- `tool_result`
-- `assistant`
-- `system`
-- `provider_debug`
+
-The logger can also receive raw structured stream events through `onRawStreamEvent()` when the host wants a low-level audit trail.
+
+
-## Plugin and Tool Policy
+
+π Repository structure
-The factory accepts:
+```
+general-agent-sdk/
+βββ src/
+β βββ index.ts β Package entry point
+β βββ public/ β Stable public API surface
+β β βββ sdk.ts β createGeneralAgentSdk()
+β β βββ session.ts β GeneralAgentSession
+β β βββ events.ts β GeneralAgentStreamEvent
+β β βββ hooks.ts β 26 hook type definitions
+β β βββ types.ts β Shared types
+β β βββ host-tools.ts β Hosted tool definitions
+β β βββ persistence.ts β Storage adapter interface
+β βββ core/
+β β βββ embedded-runner/ β Session factory + runtime
+β β βββ compaction/ β Context window compaction
+β β βββ mcp/ β MCP client (stdio + HTTP)
+β β βββ model/ β Model context window resolution
+β β βββ plugins/ β Hook runner engine
+β β βββ sessions/ β Metadata index + transcript repair
+β β βββ checkpoints/ β File checkpoint manager
+β βββ tools/ β Built-in tool implementations
+β βββ loop/ β Agent execution loop
+β βββ providers/ β LLM provider adapters
+βββ SDK DOCS/ β Runnable examples + API reference
+βββ tests/ β 133 tests (unit / integration / contract / e2e)
+βββ manifests/ β Upstream provenance tracking
+```
-- `pluginMode: "disabled" | "allowlisted" | "full-embedded"`
-- `enabledPluginIds?: string[]`
-- `hostedTools?: GeneralAgentHostedToolDefinition[]`
-- `tools?.web?.fetch?: GeneralAgentWebFetchToolOptions`
-- `tools?.web?.search?: GeneralAgentWebSearchToolOptions`
+
-This makes the host's trust boundary explicit. The SDK can preserve OpenClaw's plugin and tool semantics, but the host decides how much of that surface is enabled in embedded mode.
+---
-`web_search` is now assembled as a built-in tool by default. Internally it follows a source-synced provider runtime: Brave is selected when credentials are available, and the SDK keeps the tool present by falling back to the bundled keyless DuckDuckGo provider when no Brave key is configured.
+## π Event Reference
-Plugin scope is intentionally narrow: in this repository, plugin controls are reserved for web-related capabilities only. General-purpose non-web plugin loading is not a product goal for the SDK; other extensibility should go through built-in tools, hosted tools, MCP, or hooks.
+| Event | Payload | Description |
+|:------|:--------|:------------|
+| `assistant_delta` | `{ text }` | Streaming text chunk from the model |
+| `reasoning_delta` | `{ text }` | Extended thinking (chain-of-thought) |
+| `reasoning_end` | β | Thinking phase complete |
+| `tool_call` | `{ callId, toolName, input }` | Built-in tool invoked by the agent |
+| `tool_result` | `{ callId, toolName, output }` | Tool execution result |
+| `tool_error` | `{ callId, toolName, error }` | Tool execution failed |
+| `hosted_tool_call` | `{ callId, toolName, input }` | **Your** tool requested β SDK suspends |
+| `usage_snapshot` | `{ snapshot }` | Token usage update |
+| `compaction_started` | `{ reason }` | Context compaction in progress |
+| `compaction_finished` | `{ reason, tokensAfter? }` | Compaction complete |
+| `turn_complete` | `{ stopReason }` | Turn finished |
-## Repository Layout
+---
-```text
-src/
- index.ts # top-level export surface
- public/ # supported public API
- core/ # SDK-owned runtime implementation
- upstream/openclaw/ # extracted upstream subset only
-manifests/
- upstream-provenance.json # machine-readable provenance map
-scripts/
- sync-from-openclaw.mjs
- verify-upstream-snapshot.mjs
-tests/
- contract/
- integration/
- unit/
-docs/
- superpowers/
- specs/
- plans/
-```
+## π§° Built-in Tools
-## Development
+| Tool | Description | Category |
+|:-----|:------------|:---------|
+| `read` | Read file contents with optional line ranges | File I/O |
+| `write` | Create or overwrite files | File I/O |
+| `edit` | Surgical string-replace edits | File I/O |
+| `apply_patch` | Apply unified diff patches | File I/O |
+| `exec` | Execute shell commands | System |
+| `web_search` | Search the web (Brave / DuckDuckGo) | Web |
+| `web_fetch` | Fetch and parse web pages | Web |
+| `subagents` | Spawn scoped child agents | Orchestration |
-Install dependencies:
+---
-```bash
-pnpm install
-```
+## π Examples
-Run the main verification steps:
+All examples are **runnable** TypeScript files:
```bash
-pnpm run check
-pnpm run build
-pnpm run test
-pnpm run test:e2e
-node scripts/verify-upstream-snapshot.mjs
+export ANTHROPIC_API_KEY="sk-ant-..."
+npx tsx "SDK DOCS/01-hello-world.ts"
```
-## Upstream Provenance
+| # | Example | What it covers |
+|:--|:--------|:---------------|
+| 01 | [`hello-world.ts`](./SDK%20DOCS/01-hello-world.ts) | Minimal agent, first `streamTurn()` call |
+| 02 | [`multi-turn-chat.ts`](./SDK%20DOCS/02-multi-turn-chat.ts) | Interactive REPL with memory |
+| 03 | [`hosted-tools.ts`](./SDK%20DOCS/03-hosted-tools.ts) | Custom tool with suspend/resume |
+| 04 | [`session-lifecycle.ts`](./SDK%20DOCS/04-session-lifecycle.ts) | Create, resume, fork, reset |
+| 05 | [`hooks.ts`](./SDK%20DOCS/05-hooks.ts) | Lifecycle hooks in action |
+| 06 | [`mcp-servers.ts`](./SDK%20DOCS/06-mcp-servers.ts) | Dynamic MCP integration |
+| 07 | [`compaction.ts`](./SDK%20DOCS/07-compaction.ts) | Context window management |
+| 08 | [`subagents.ts`](./SDK%20DOCS/08-subagents.ts) | Child agent delegation |
+
+> π Full API documentation: [`SDK DOCS/API-REFERENCE.md`](./SDK%20DOCS/API-REFERENCE.md)
-This repository deliberately does not mirror the entire upstream OpenClaw source tree.
+---
-Instead:
+## π§ Development
-- copied upstream snapshots live under `src/upstream/openclaw/`
-- source-synced adapted files may also live in normal SDK paths such as `src/tools/` and `src/security/`
-- each extracted file is tracked in [`manifests/upstream-provenance.json`](./manifests/upstream-provenance.json)
-- provenance can be revalidated with `node scripts/verify-upstream-snapshot.mjs`
+```bash
+pnpm install # Install dependencies
+pnpm run check # Type check
+pnpm run build # Build
+pnpm run test # 133 unit + integration tests
+pnpm run test:e2e # Package smoke test
+node scripts/verify-upstream-snapshot.mjs # Verify provenance
+```
-This is a hard boundary, not just documentation.
+---
-## Host Integration
+
-A host application typically keeps the following responsibilities outside the SDK:
+
-- canonical `session.json`
-- dual-session switching
-- channel ingress and owner notifications
-- cross-engine continuity journal
-- top-level profile and environment management
+**MIT** Β· Built by [BabelCloud](https://github.com/babelcloud)
-That design keeps the General Agent SDK as an execution backend rather than turning the host into an OpenClaw runtime shell.
+
-## Specifications and Implementation Notes
+If this project helps you build something cool, give it a β β it helps others find it too.
-- Design spec: [`docs/superpowers/specs/2026-03-31-general-agent-sdk-source-sync-design.md`](./docs/superpowers/specs/2026-03-31-general-agent-sdk-source-sync-design.md)
-- Implementation plan: [`docs/superpowers/plans/2026-03-31-general-agent-sdk-source-sync.md`](./docs/superpowers/plans/2026-03-31-general-agent-sdk-source-sync.md)
+
-These documents are the source of truth for architecture, boundary rules, continuity requirements, and integration sequencing.
+