This document is a specification for the definition, execution, and schema generation of Tool (function tool).
We aim for the “minimum and correct form” when converting the Python version of @tool and Depends to TS.
- Tool: A function that the model can call with tool call. Input is JSON (constrained by schema)
- Tool definition: "Tool list" (name/description/JSON Schema) to be passed to LLM
- DI: A mechanism to resolve and inject dependencies (DB clients, etc.) when running the tool
In TS, the “data + function” form is easier to handle than the decorator.
export type DefineToolOptions<TInput, TResult> = {
name: string;
description: string;
input: ZodSchema<TInput>;
execute: (input: TInput, ctx: ToolContext) => Promise<TResult> | TResult;
};
export type Tool = {
name: string;
description: string;
definition: ToolDefinition; // parameters are JSON Schema
executeRaw: (rawArgsJson: string, ctx: ToolContext) => Promise<ToolResult>;
};By moving executeRaw to the Tool side, the Agent side can
- JSON parse
- Validation
- Exception → ToolMessage
can be treated as a “Tool common” implementation.
export type ToolContext = {
signal?: AbortSignal;
logger?: Logger;
now?: () => Date;
// dependency overrides / injection
deps: Record<string, unknown>;
resolve: <T>(key: DependencyKey<T>) => Promise<T>;
};Tool extracts dependencies using ctx.resolve(...) (or you can directly reference ctx.deps).
- Enable LLM to produce “correct argument form”
- Validate invalid arguments before tool execution (zod validate)
- Ability to generate JSON Schema from zod schema
- Must be able to attach constraints equivalent to
additionalProperties: false(If not, reject on the Tool side) - Built-in
defineTooldefinitions use explicit non-strict function calling so Zod optional/defaulted fields remain optional and model-visible schemas stay compact. - Runtime Zod parsing remains authoritative and rejects invalid generated arguments before execution.
- External/client tools may still request provider strict mode when their supplied schema is compatible (see providers spec for details).
*Use Zod v4's toJSONSchema (target: "draft-07" / io: "input").
Properties that the Python version of Depends satisfies:
- Dependencies can be resolved with either sync/async
- Can be overridden (replaced)
In TS, it is easy to understand that the “dependency resolution key” is explicitly specified and handled.
export type DependencyKey<T> = {
id: string;
create: () => T | Promise<T>;
};
export type DependencyOverrides = Map<string, () => unknown | Promise<unknown>>;- If
overrideshas the sameid, use it - If not, call
create() - Values may be cached for the duration of a single tool call (“per-run” caching if necessary)
CLI is often used to replace file operation root'' and work directory'' with DI.
export type ToolResult =
| { type: 'text'; text: string }
| { type: 'parts'; parts: ContentPart[] }
| { type: 'json'; value: unknown };text→ToolMessage.contentis stringjson→ JSON.stringify (for stability)parts→ToolMessage.contentare parts
Tool exceptions are converted to ToolMessage(is_error=true, content="Error executing tool: ...").
While tool output is "kept in context as much as possible", if the total size limit is exceeded,
Trim from old output and leave reference ID. See dev-docs/specs/context-management.md for details.
ToolMessage may be given output_ref (reference ID).
Multimodal parts must remain structured in the live ToolMessage through
tool-output cache processing. The current text-only cache store may persist a
placeholder projection for lookup, but it must not replace the image/document
parts before the next model call.
TODO:
- Implementation of tool_output_cache / tool_output_cache_grep supports streaming in case of large output.
- Extend the cache store to save and retrieve typed content parts, not only their text projection.
doneis recommended as a “termination tool”- Not required (normally ends with response without tool call)
Planning (write_todos, etc.) is not required for core, but is provided as a standard CLI tool.
With this design:
- Library usage can be kept to a minimum
- Using CLI can reduce the volatility of plans
Current runtime todo tooling:
todo_read: shows execution order, summary counts, and next actionable task.todo_new: start/restart the plan with a new full list.todo_append: append discovered tasks while keeping current items.todo_patch: partially update/remove items by stableid; omitted patch fields keep their current values.todo_clear: clear the entire todo list for the current session.- Todo item fields include
id,content,status,priority(1-5), optionalnotes, optionalactiveForm. - Runtime validates that
in_progressitems are at most one so agents can process tasks one-by-one. - Todo state is persisted in session snapshot metadata (
SessionState.meta.codelia_todos) and restored when resuming withrun.start.session_id.
Standard tool to get the contents from the reference ID of the tool output cache.
- name:
tool_output_cache - input:
{ ref_id: string, offset?: number, limit?: number } - output: text with line numbers (similar to
read) - default behavior: clip/truncate preview output and include continuation hints
A standard tool that searches against the reference ID of the tool output cache.
- name:
tool_output_cache_grep - input:
{ ref_id: string, pattern: string, regex?: boolean, before?: number, after?: number, max_matches?: number } - output: text with line numbers (similar to
grep)
A standard tool that reads one cached physical line by character window.
- name:
tool_output_cache_line - input:
{ ref_id: string, line_number: number, char_offset?: number, char_limit?: number } - output: text with segment metadata and continuation hint
Standard fallback tool for web search when provider-native search is not used.
- name:
search - input:
{ query: string, max_results?: number, backend?: "ddg" | "brave", allowed_domains?: string[] } - output: JSON summary of search candidates (
title/url/snippet/source)
Structured multi-file edit tool for codex-style patch text.
- name:
apply_patch - input:
{ patch: string, dry_run?: boolean } - patch payload: codex-style
*** Begin Patch/*** End Patchenvelope withAdd File/Delete File/Update Filesections - update chunk rule:
@@chunk headers may omit unified-diff line numbers; context-only chunks are allowed, but eachUpdate Filesection must contain at least one+or-change unless it is a move-only update - output: JSON summary including
summary,file_count,files, and boundeddiffpreview (diff_cache_idwhen full diff is cached) - note: current codelia implementation keeps this as a normal JSON function tool carrying patch text, not a transport-level freeform tool
Standard tool to fetch and normalize a specific URL after search/native search picks a candidate.
- name:
webfetch - input:
{ url: string, output_format?: "markdown" | "text" | "html", timeout_ms?: number, max_bytes?: number } - output: JSON summary including
status,content_type,title, normalizedcontent, and truncation metadata - note: intentionally treated as external access for permission policy, so it is not in the default system allowlist
Read-only local image inspection tool.
- name:
view_image - input:
{ file_path: string, detail?: "auto" | "low" | "high", max_bytes?: number } - output: multimodal content parts (
text+image_url) - supported file types:
png/jpeg/webp/gif - note: uses the same sandbox path semantics as other local file tools
The edit tool semantics are defined in dev-docs/specs/edit-tool.md.