An agent runtime for TypeScript.
One package — query(), the dispatcher, the permission flow, replay,
evals, and adapters for Anthropic / OpenAI / OpenAI-compat / MCP /
OpenTelemetry. No plugin registry. No internal types you can't see.
import { query, tool } from '@fuloo/sdk';
import { anthropic } from '@fuloo/sdk/anthropic';
import { z } from 'zod';
const readFile = tool({
name: 'read_file',
description: 'Read a file from disk.',
input: z.object({ path: z.string() }),
isReadOnly: true,
async run({ path }) {
return await Bun.file(path).text();
},
});
for await (const ev of query({
prompt: 'Summarise package.json in one sentence.',
provider: anthropic(),
model: 'claude-opus-4-7',
tools: [readFile],
})) {
if (ev.type === 'text_delta') process.stdout.write(ev.text);
if (ev.type === 'approval_request') ev.decide('allow');
}| Tool loop | Zod-typed input/output, parallel by default, per-call concurrency policy |
| Multi-agent | subagent (delegate) and handoff (transfer) as distinct primitives |
| Skills | defineSkill packages a system prompt + tools + provider as one tool |
| Deferred schemas | _tool_search synthesised on demand — 100 tools don't blow up context |
| Replay | Record byte-identical tapes, replay deterministically, assert via scenarios |
| Evals | runEvals + Metric + assertEvals for threshold-gated regression |
| Persistence | Pluggable SessionStore and CheckpointStore protocols |
| Observability | One AgentEvent stream feeds UI, OTel traces, and replay tapes |
| Typed deps | query<_, MyDeps>({ deps }) → ctx.deps typed in every tool body |
| HITL | Approval, pause, and pushUserMessage as distinct event-mailbox primitives |
bun add @fuloo/sdkPlus whichever subpath peer dep your code imports:
| Subpath | Peer dep |
|---|---|
@fuloo/sdk/anthropic |
@anthropic-ai/sdk |
@fuloo/sdk/openai |
openai |
@fuloo/sdk/openai-compat |
openai |
@fuloo/sdk/mcp |
@modelcontextprotocol/sdk |
@fuloo/sdk/otel |
@opentelemetry/api |
Requires Node ≥ 22 or Bun ≥ 1.1, ESM only.
import {
query, tool, hook, subagent, handoff,
defineSkill, withMemory, withBudget,
replayProvider, recordingSink,
runEvals, passIf, assertEvals,
} from '@fuloo/sdk';Internal modules are not exported — what isn't on @fuloo/sdk isn't
part of the contract.
Runnable examples live in examples/ — most are offline
(no API key needed), a few are provider-backed:
| Path | What it shows |
|---|---|
hello/ |
The shortest run; AsyncIterable<AgentEvent> |
cli-repl/ |
Multi-turn as (SessionStore, sessionId) — CLI shape |
server-bun/ |
Live Bun.serve SSE handler with two POSTs sharing one session |
subagent/ |
subagent vs handoff side by side |
skills/ |
defineSkill and a parent picking one out of two |
replay/ |
Record → replay byte-identically → assert via scenarios |
evals-demo/ |
runEvals + custom Metric + threshold gate |
typed-deps/ |
ctx.deps typed end-to-end across tools |
trace-otel-live/ |
Real OTel BasicTracerProvider pipeline |
mcp-per-user/ |
tools: (ctx) => ... resolver + bridge cache |
persistence/session-fs/ |
Filesystem-backed SessionStore |
persistence/checkpoint-fs/ |
Mid-run crash recovery via CheckpointStore |
| Doc | Thesis |
|---|---|
multi-turn |
会话不是对象,是 (SessionStore, sessionId) 二元 |
tool-scaling |
100 个 tool 不写 100 行——三层应对 |
mcp-lifecycle |
bridge 是连接,不是数组 |
hitl |
Human-in-the-loop 是四种暂停,不是一种 |
Four short essays in docs/design/ document fuloo's
identity. Not required reading to use the SDK.
MIT.