SDKs & Tooling
Chidori ships as a single Rust binary. There are two SDKs — a TypeScript SDK (npm) and a Python SDK (pure stdlib, no deps) — both pure HTTP clients to a running chidori serve. Tools live in .ts files next to your agents. This page covers what you install and how the pieces fit together.
Project layout
A typical Chidori project:
my-project/
├── agents/ # .ts agent files
│ ├── summarizer.ts
│ └── webhook.ts
├── prompts/ # Jinja templates
│ └── research.jinja
├── tools/ # .ts tool files
│ └── search.ts
└── examples/
└── legacy-starlark/ # archived .star agentsThe runtime looks for agents in agents/, tools in tools/, and prompts in prompts/ relative to the project root. Legacy .star agents are archived under examples/legacy-starlark/.
The CLI
chidori run [--input key=value]... [--stream] [--trace] [--replay session.json]
chidori check
chidori tools [--dir ]...
chidori serve [--port 8080]
chidori demo
chidori trace
chidori snapshot Install the runtime with cargo install chidori (or cargo build from source).
Input formats for run:
--input key=value— string value--input key=@file.txt— read the value from a file--input '{"key": "value"}'— JSON object merged into inputs
Provider environment variables:
ANTHROPIC_API_KEY— use Anthropic directly (claude-*models)OPENAI_API_KEY— use OpenAI directly (gpt-*,o1-*,o3-*)LITELLM_API_URL+LITELLM_API_KEY— use a LiteLLM proxy (or any OpenAI-compatible endpoint) as a catch-all
Defining tools
A tool is a .ts module that exports tool metadata — a ToolDefinition with a name, description, and a JSON Schema for its parameters — alongside export async function run(args, chidori). The metadata is what the model sees for function-calling; run is what executes.
tools/search.ts
export const tool = {
name: "web_search",
description: "Search the web and return results.",
parameters: {
type: "object",
properties: {
query: { type: "string" },
maxResults: { type: "number", default: 5 },
},
required: ["query"],
},
}
export async function run(args, chidori) {
const response = await chidori.http("https://api.search.example/search", {
query: { q: args.query, limit: args.maxResults ?? 5 },
})
return response.results
}tools/analyze.ts
export const tool = {
name: "analyze",
description: "Run heavy analysis via external service.",
parameters: {
type: "object",
properties: { data: { type: "object" } },
required: ["data"],
},
}
export async function run(args, chidori) {
return chidori.http("http://localhost:9000/analyze", {
method: "POST",
body: { data: args.data },
})
}For tools that need native libraries, wrap an external service over HTTP — it keeps the tool surface simple and side effects visible in the call log. MCP-backed remote tools are also supported.
List registered tools:
chidori tools --dir tools/The TypeScript SDK
The TypeScript SDK is published to npm and is a pure HTTP client to a running chidori serve.
import { AgentClient, Checkpoint } from "chidori";
const client = new AgentClient("http://localhost:8080");
// Run an agent — live LLM calls
const session = await client.run({ document: "Rust is great." });
console.log(session.output); // { summary: "...", actionItems: "..." }
console.log(session.status); // "completed"
// Save and replay
await session.checkpoint().save("session.json");
const replayed = await client.replay(await Checkpoint.load("session.json"));
// List sessions on the server
for (const s of await client.listSessions()) {
console.log(s.id, s.status);
}The Python SDK
The Python SDK is pure stdlib — no pip install, no native bindings, no dependencies. It's the same HTTP client surface, talking to a running chidori serve.
from chidori import AgentClient, Checkpoint
client = AgentClient("http://localhost:8080")
# Run an agent — live LLM calls
session = client.run({"document": "Rust is great."})
print(session.output) # {"summary": "...", "action_items": "..."}
print(session.status) # "completed"
# Save and replay
checkpoint = session.checkpoint()
checkpoint.save("session.json")
cp = Checkpoint.load("session.json")
replayed = client.replay(cp)
assert replayed.output == session.output
# Iterate over many documents
for doc in documents:
s = client.run({"document": doc})
s.checkpoint().save(f"checkpoints/{s.id}.json")
# List sessions on the server
for s in client.list_sessions():
print(s["id"], s["status"])The Rust runtime
If you need to embed Chidori in a larger Rust service, the runtime is a library crate. The chidori CLI binary is a thin wrapper around it. See the Rust API docs for the RuntimeContext and HostFunction traits if you want to add new host functions or swap the LLM provider layer.
Output format
Agent output is always JSON on stdout — whatever your agent function returns, serialized:
- Objects → JSON objects
- Arrays → JSON arrays
- Strings → JSON strings
- Numbers → JSON numbers
- Booleans → JSON booleans
null/undefined→ JSON null
Traces and diagnostics go to stderr, so you can pipe stdout into jq cleanly:
chidori run agents/summarizer.ts --input document=@notes.txt | jq '.summary'