Host Functions
Host functions are the only way a Chidori agent interacts with anything outside its own code. They live on the injected chidori object and are the one and only side-effect boundary — every call is logged, cacheable, and replayable. This page is the reference.
chidori.prompt(text, options?) → string | object
Send a message to an LLM. Returns the response as a string, or as parsed JSON when type labels a structured stream such as "json".
// Simple
const answer = await chidori.prompt("What is 2+2?");
// Full options
const result = await chidori.prompt("Analyze this data: " + data, {
type: "json",
model: "claude-opus",
temperature: 0.2,
maxTokens: 4000,
tools: ["web_search", "calc"],
});type labels streamed output (e.g. "progress", "draft", "subagent", "final", "json"). When tools: [...] is set, the LLM can autonomously invoke those tools.
chidori.template(strOrPath, vars) → string
Render a Jinja2 template with minijinja. Accepts either an inline string or a path ending in .jinja / .j2:
let text = await chidori.template("Hello {{ name }}!", { name: "Alice" });
text = await chidori.template("prompts/analysis.jinja", { items, role: "analyst" });
const answer = await chidori.prompt(
await chidori.template("prompts/research.jinja", { topic, sources }),
);Supports the full Jinja feature set: conditionals, loops, filters, includes, inheritance.
chidori.tool(name, args) → any
Invoke a registered tool. Tools live in tools/*.ts — each module exports tool metadata and a run function (see Composition):
const results = await chidori.tool("web_search", { query: "rust programming", maxResults: 5 });
const data = await chidori.tool("fetch_url", { url: "https://example.com" });chidori.callAgent(path, input) → any
Call another .ts agent as a sub-agent. It shares the parent runtime context and call log:
const summary = await chidori.callAgent("summarizer.ts", { document: longText });
const checked = await chidori.callAgent("fact_checker.ts", { claims: summary });chidori.parallel(fns) → array
Run an array of functions concurrently (Promise.all semantics), preserving result order:
const results = await chidori.parallel(
queries.map((q) => () => chidori.tool("web_search", { query: q })),
);chidori.input(message, options?) → string
Pause execution and wait for a human response. Used for approval flows, clarification, or any human-in-the-loop step. The runtime saves a checkpoint and suspends the run; resume by POSTing to /sessions/{id}/resume.
const approved = await chidori.input("Proceed with this plan?", {
type: "approval",
choices: ["yes", "no"],
default: plan,
});
if (approved === "yes") {
await execute(plan);
}Options include type, choices, and default.
chidori.execJs / execPython / execWasm(code, options?) → any
Run arbitrary code in a sandbox. Typically used to execute code an LLM generated at runtime. There are dedicated entry points per runtime:
const code = await chidori.prompt("Write Python to analyze this CSV:\n" + data, {
type: "draft",
});
const result = await chidori.execPython(code, { timeoutMs: 30000 });execJs, execPython, and execWasm (which takes base64 bytes) each accept limits such as { timeoutMs }. The sandbox has no filesystem, network, or host access.
chidori.http(url, options?) → object
Make an HTTP request:
const resp = await chidori.http("https://api.example.com/data", {
method: "GET",
headers: { Authorization: "Bearer " + token },
});
const submitted = await chidori.http("https://api.example.com/submit", {
method: "POST",
body: { key: "value" },
});Options: method, headers, query, body, timeoutMs.
chidori.memory(action, ...) → any
Persistent storage that survives across agent runs. Supports key-value and vector storage. Actions: "set", "get", "list", "delete", "clear":
await chidori.memory("set", "user_pref", "dark mode");
const pref = await chidori.memory("get", "user_pref");
const keys = await chidori.memory("list");chidori.log(message, data?) → void
Structured logging. Appears in traces and stderr under --verbose:
chidori.log("Processing batch", { count: items.length, batchId: id });chidori.env(name) → string | undefined
Read an environment variable. Returns undefined if unset:
const apiKey = chidori.env("MY_API_KEY");chidori.retry(fn, options) → any
Retry a function on failure with configurable backoff:
const result = await chidori.retry(
() => chidori.prompt("Translate to French:\n" + text),
{ attempts: 3, delayMs: 500, backoff: "exponential" },
);Options: attempts, delayMs, backoff.
chidori.tryCall(fn) → { ok, error }
Execute a function and capture errors as values instead of throwing:
const result = await chidori.tryCall(() => chidori.tool("flaky_api", { query: text }));
if (!result.ok) {
chidori.log("API failed", { error: result.error });
}chidori.checkpoint(name, metadata?) → void
Write an explicit marker into the call log to make a run easier to inspect and branch:
chidori.checkpoint("after_search", { count: results.length });The closed set
That's the surface. Every interaction with the outside world flows through a chidori host call — which is exactly the property that makes checkpointing, replay, and deterministic testing possible.
