zidane/ types
Type-only access to the public agent, session, context, decision and hook types, plus the typed error classes.
import { … } from 'zidane/types'src/types-export.ts
Use zidane/types when you only need to name a type, for example in a shared package that never creates an agent. Import with import type and the entry adds nothing to your bundle. The page lists agent options and hooks, session turns and usage, execution contexts, decisions and MCP connections.
import type { Agent, AgentOptions, SessionTurn } from 'zidane/types'
import { createAgent } from 'zidane'
import { basic } from 'zidane/presets'
import { anthropic } from 'zidane/providers/anthropic'
const options: AgentOptions = { ...basic, provider: anthropic() }
const agent: Agent = createAgent(options)
function lastTurn(turns: SessionTurn[]): SessionTurn | undefined {
return turns[turns.length - 1]
}
console.log(lastTurn([]), agent.hooks !== undefined)Functions#
flattenTurnsFunction#
Depth-first walk over the stats tree, returning every TurnUsage entry
— parent loop first, then each child subtree in completion order.
AgentStats.totalIn and the other total* fields already sum the whole
tree. Anything that needs per-turn data across the tree, such as a
per-model rollup, walks through this.
statsByModelFunction#
Group cumulative usage by TurnUsage.modelId. Each entry sums the input,
output, cache, cost, and turn-count across every turn the tree attributed
to that model — naturally handling cross-model runs (vision-fallback,
model-shifted subagents, mixed-provider workflows).
Turns missing modelId (mock providers, providers that don't echo a model
id) are bucketed under the literal string '(unknown)'.
toolOutputBudgetByteLengthFunction#
Approximate text-budget size of a tool output, in bytes.
Structured attachment blocks count as the short markers produced by
toolResultToText, not as raw base64 payload bytes. The per-turn
toolOutputBudget is a readability/context-loading steering guard; a
vision/PDF-capable provider can receive attachment bytes without needing the
model to summarize them as if they were text output.
toolOutputByteLengthFunction#
Approximate wire payload size of a tool output, in bytes.
- Plain text: UTF-8 byte length.
- Structured content: text blocks contribute their UTF-8 byte length; image
blocks contribute their base64 character length — a proxy for the
serialized request-body footprint, NOT for tokens. Vision encoders
tokenize decoded pixels (geometry-dependent; e.g. Anthropic ≈
w·h/750, OpenAI ≈ 85 + 170/tile), which has no meaningful relationship to base64 length.
Used by the agent loop to populate outputBytes on tool:after,
tool:transform, mcp:tool:after, and mcp:tool:transform hooks so
consumers can size-budget tool output without re-counting bytes themselves.
Suitable for wire-size telemetry; the per-turn toolOutputBudget uses
toolOutputBudgetByteLength so attachments do not trigger text-output
summarization nudges by themselves. NOT a substitute for provider-side
context-window accounting — defer to server-side context management (e.g.
Anthropic's context-management-* beta) when token accuracy matters.
toolResultToTextFunction#
Lossy flattener — converts ToolResultContent[] (or a plain string) to a single
string. Non-text blocks are replaced with markers such as
[image: <media>, <n> b64 bytes] (a ref block shows ref <ref> in place of the size).
Use at UI boundaries where a string is required; providers that understand structured content should route the array through without flattening.
Constants#
DEFAULT_AGENT_CLOCKConstant#
Native clock backing the default (Date.now + crypto.randomUUID).
Interfaces#
AgentBehaviorInterface#
Run behavior settings: limits, guards, caching, compaction and recovery policies. Set agent-wide on AgentOptions.behavior and override per run.
AgentClockInterface#
Time + UUID source. Defaults to Date.now() and crypto.randomUUID().
Scoped to journaled metadata — every callsite that lands in
SessionTurn.id, SessionTurn.createdAt, runId, turnId, or hook
payloads consumers may persist. Live-only measurements (TTFT deltas,
elapsed counters) keep Date.now() directly so they reflect real
wall-clock progress.
now() may return a Promise<number>: the loop awaits it at every
callsite. randomUUID() stays synchronous so a clock can provide
replay-stable identifiers without async metadata plumbing.
Precedence: AgentRunOptions.clock > AgentOptions.clock >
DEFAULT_AGENT_CLOCK. A run on a replay-mode durable runtime
(AgentOptions.durable) takes its time and ids from the runtime instead,
so a replay regenerates byte-identical session metadata.
AgentDecideInterface#
agent.decide / ctx.decide. Never throws by default: failures come back as
{ ok: false, reason }. Pass { throw: true } to get a DecisionError instead.
AgentDecisionsOptionsInterface#
Agent-level configuration for decisions (AgentOptions.decisions).
AgentRunOptionsInterface#
Options for one Agent.run call.
AgentStatsInterface#
Token, cost and timing totals returned by Agent.run.
ChildRunStatsInterface#
Stats of one spawned subagent run, passed to spawn:complete and listed in AgentStats.children.
DecideHookContextInterface#
Present on every hook context except decision:* (see AgentHookHandlers).
DecisionEndHookContextInterface#
Context passed to the decision:end hook.
DecisionFailureInterface#
A decision that produced no answers. See DecisionFailureReason.
DecisionRequestInterface#
Input to agent.decide and ctx.decide: the evidence and the questions to answer about it.
DecisionStartHookContextInterface#
Context passed to the decision:start hook.
DecisionSuccessInterface#
A decision that produced answers.
DecisionUsageInterface#
Token usage of one decision call.
McpServerConfigInterface#
Configuration of one MCP server the agent connects to and exposes as tools.
McpToolHookContextInterface#
Base context for MCP tool hooks.
tool is the native tool name on the MCP server. server is the configured server
name. The canonical zidane-namespaced identity is mcp_{server}_{tool}.
displayName equals the canonical namespaced name unless the agent has aliased
this MCP tool via AgentOptions.toolAliases; in which case displayName is the
alias that the LLM sees.
ModelUsageInterface#
Per-model usage rollup produced by statsByModel.
turns counts the number of TurnUsage entries attributed to the model
across the whole tree (parent loop + every recursively-spawned child).
Cache and cost numbers are summed from the same set of turns.
MutationValidationBatchInterface#
Successful mutations from one tool-results round, passed to validate.
MutationValidationFailureInterface#
Details of a failed validation, passed to onFailure.
MutationValidationHooksOptionsInterface#
Options for createMutationValidationHooks.
MutationValidationMutationInterface#
One successful file mutation (created, updated or edited) made by a tool call.
OAuthRefreshHookContextInterface#
Context for OAuth refresh hooks
PromptAudioPartInterface#
Audio attachment in a multimodal prompt.
PromptDocumentPartInterface#
Document attachment in a multimodal prompt.
PromptImagePartInterface#
Image attachment in a multimodal prompt.
PromptTextPartInterface#
Text part of a multimodal prompt.
PromptVideoPartInterface#
Video attachment in a multimodal prompt.
QueuedUserMessageInterface#
A user message that waits in a run's steering or follow-up queue
(Agent.steer, Agent.followUp). The loop adds it as a user turn.
RepeatGuardConfigInterface#
Configuration for the consecutive-identical-call repeat guard. See
AgentBehavior.repeatGuard for the full contract.
ResolveContentRefBlockInterface#
Block passed to a ResolveContentRef callback.
RetryConfigInterface#
Configuration for the loop's retry-with-backoff policy around
provider.stream(). See AgentBehavior.retry.
SessionHookContextInterface#
Base context for session hooks
SessionMessageInterface#
One message of a session conversation, as sent to the provider.
SessionTurnInterface#
One persisted turn of a session: a user prompt, an assistant response, or a system or command entry.
SpawnHookContextInterface#
Base context for spawn hooks
StagedToolStateInterface#
Staging handle behind a ToolStateView: the seam a durable run
uses to move a call's mutations through its step record. Not part of
the tool-facing surface; resolve it with stagedToolState.
StreamHookContextInterface#
Context for stream hooks
ToolHookContextInterface#
Base context for tool execution hooks: the tool call a tool:* hook fires
for, with ids, names, input and the run it belongs to.
name is the canonical tool identity — the spec name registered on the agent (or the
mcp_{server}_{tool} name for MCP tools). Hooks should policy-match against name.
displayName is the outward-facing name — the alias surfaced to the LLM when
AgentOptions.toolAliases maps the canonical name; otherwise equal to name.
UI/telemetry adapters should emit displayName.
Canonical vs. alias matters on session resume: session.turns persists canonical
names only, so renaming an alias cannot desync history.
ToolResultAudioContentInterface#
Audio tool-result block with inline base64 data.
ToolResultDocumentContentInterface#
Document tool-result block with inline data.
ToolResultDocumentRefContentInterface#
Document tool-result block that carries a content reference instead of inline data.
ToolResultImageContentInterface#
Image tool-result block with inline base64 data.
ToolResultImageRefContentInterface#
Image tool-result block that carries a content reference instead of inline data.
ToolResultTextContentInterface#
Text tool-result block.
ToolResultVideoContentInterface#
Video tool-result block with inline base64 data.
ToolStateControllerInterface#
Per-agent owner of the snapshot + per-call staging.
One controller per agent instance: the snapshot is shared across runs (so state written in run 1 is visible in run 2 without a reload), while each tool call gets its own view so its mutations can be journaled and committed independently.
ToolStateStoreInterface#
Durable backing for tool state. NOT runtime-specific — implement it against whatever the host already trusts with durable writes.
load runs once per agent instance, before any tool dispatch. commit
receives the ops staged by one tool call, in the order the tool made them.
Two requirements on commit:
- Idempotent. A durable adapter may hand the same ops twice if the invocation is retried before the commit is recorded.
- Non-throwing, ideally. A rejection does not fail the tool call — the
body already ran and its side effects already happened, so the dispatch
path reports the failure (the
tool-state:commit-failedhook, else a stderr line) and drops the write rather than killing the run. Retry inside your implementation if the write matters more than the latency.
ToolStateViewInterface#
Tool-facing view. Reads hit the hydrated snapshot merged with this call's own staged writes; writes stage an op (see the module docstring for why they aren't written through).
TurnUsageInterface#
Token usage and timing for one turn.
Types#
AgentHookBusType#
agent.hooks: the agent's hookable, with registration typed through
AgentHookHandlers (so handlers see ctx.decide) while callHook
keeps the raw AgentHooks context shapes.
AgentHookHandlersType#
Handler signatures as consumers see them: identical to AgentHooks
except object contexts also carry DecideHookContext.decide. The
agent attaches it (non-enumerable) right before handlers run, so code that
fires hooks builds contexts without it.
AgentToolStateType#
Read-only window over an agent's durable tool state — the read half of the
ToolStateView a tool sees through ToolContext.state, minus
the write path. Backed by ToolStateController.committed, so a host
reads exactly what the tools have committed so far; a call's staged writes
stay invisible until it settles.
Reads are lazy: they resolve against the live state at call time, so a read
inside a turn:after / agent:done hook sees every commit from the turn
that just settled. The state hydrates from the configured
AgentOptions.toolState store at run start (memoized on success,
retried on a failed load) — before the first run, reads report only what
this process has committed, which for a fresh agent is nothing. Read after
a run, not before.
There is no set: a host-level write has no tool result to be journaled
with, so it would not survive a durable replay — exposing it would
reintroduce exactly the class of bug the staging design exists to prevent.
Mutate state from inside a tool.
Scope is this agent instance only. Tool state is NOT inherited by subagents
(spawn starts a fresh controller), so this view never reflects a child's
writes.
DecisionAnswerType#
Answer to one question: a predicate, choice or score answer, or a refusal.
DecisionAnswersType#
Answers keyed by question name, each typed from its question.
DecisionFailureReasonType#
Why a decision produced no answers:
unavailable: decisions disabled, no capable provider, missing credentials, or unknown modelauth: the provider rejected the credential (401/403)unsupported: the input can't be expressed on this provider's wire (e.g. images)timeout/aborted: wall-clock cap hit / caller or run cancelledrate_limited/quota: 429 or 529 / 402invalid: the request failed validation, or the response was malformederror: anything else (5xx, network)
DecisionInputType#
The evidence the questions are evaluated against:
- a string,
- a JSON object of related context,
- multimodal prompt parts (text + images; support varies per provider).
DecisionOutcomeType#
Result of a decision: a DecisionSuccess or a DecisionFailure. Narrow on ok.
DecisionQuestionType#
One question: a predicate, a choice or a score.
DecisionQuestionsType#
Questions keyed by name. The name keys the matching answer.
MutationValidationResultType#
Result of a validation: { ok: true }, or { ok: false } with an optional message and error list.
ProgressNudgeKindType#
Stall pattern that can trigger a progress nudge. See AgentBehavior.progressNudges.
ProgressNudgeMessageType#
Message a progress nudge steers the model with: a fixed string, or a function of the nudge kind and its trigger count.
PromptPartType#
One block of a multimodal user prompt.
agent.run({ prompt }) accepts either a plain string (treated as a single
text part) or an array of these parts for multimodal inputs.
document parts are routed per provider: PDF-style mime types are sent as
native document blocks when the provider supports them; text documents are
inlined as text with an attachment header. Providers that cannot handle an
image or document throw early.
QueuedMessageOptionsType#
What Agent.steer and Agent.followUp take besides the prompt.
RepeatGuardToolMatcherType#
Per-tool predicate selecting which tools the RepeatGuardConfig
watches. A bare string matches that exact canonical name; a function
receives the canonical name and returns true to track it.
ResolveContentRefType#
Host callback that resolves a content reference to its payload. Called at provider wire time with the block that holds the ref.
RunHookMapType#
Per-run hook registrations. Each entry can be a single handler or an array of handlers.
Keys are AgentHooks event names (loose-typed here to avoid a circular import; agent-run.ts
validates the event names at run time, and AgentHookMap is the strongly-typed form).
SessionContentBlockType#
Content block of a session message: text, media, a tool call, a tool result, or thinking.
text, tool_call and thinking blocks can carry a signature: opaque
state the producing API wants back with that block (a Gemini thought
signature, an Anthropic thinking HMAC, OpenAI encrypted reasoning), tagged
with its SignatureProducer. Only that provider's wire builder reads
it; the others map blocks field by field and never send it.
SessionEndStatusType#
How a run ended: 'completed', 'aborted' or 'error'.
SuccessfulMutationOutcomeType#
Tool outcomes that count as a successful mutation.
ThinkingLevelType#
One of the THINKING_LEVELS strings: how much the model reasons before it answers.
ToolOutcomeType#
Structured side-effect outcome for mutating tools (write_file, edit,
multi_edit, and custom tools that opt in via ToolContext.reportOutcome).
Surfaced on tool:after.outcome so hosts can build no-op-resistant loop
guards ("did this edit actually change bytes?") WITHOUT string-matching the
result prose (Created /Updated /No change needed …), which is fragile
across versions. Absent on tool:after for read-only tools and any tool
that never calls reportOutcome.
created— a new file/resource was written.updated— an existing file/resource changed (full overwrite differed).edited— a surgical in-place change applied at least one replacement.noop— the call succeeded but changed zero bytes (idempotent write, replacement that produced identical content).failed— the mutation was attempted but did not take effect (error, stale-read rejection, no-match). Pairs withisErroron the wire result; reported explicitly so guards don't have to infer.
ToolResultContentType#
A single block of structured tool-result content.
MCP servers can return a mix of text, image, audio, video, and resource blocks.
Tools return string for the common text-only case or ToolResultContent[] when
they need to preserve non-text content (e.g. screenshots from a browser MCP).
Providers that support native multi-part tool results (Anthropic, OpenAI Codex via pi-ai) route image blocks into their wire format verbatim; OpenAI-compat providers route them via a companion-user-message fallback when the underlying model/endpoint does not accept images inside tool-role messages.
ToolResultMetadataType#
Provider/model-invisible metadata associated with a tool result. Hooks use this to persist telemetry about transforms (compression, redaction, etc.) without adding model-visible text to the result body. Hooks can read it; the model never sees it.
ToolStateOpType#
One staged mutation. JSON-shaped on purpose: durable adapters journal
these verbatim, so a tagged union with an explicit delete flag beats
value: undefined (which JSON drops).
TurnFinishReasonType#
Reason the provider gave for stopping the turn.
'stop'— natural turn end (end_turn/stop_sequence).'tool-calls'— model emitted tool_use blocks.'length'—max_tokensreached, or (Anthropic 4.6+) the response bumped against the model's context window mid-stream (model_context_window_exceeded). The partial response is preserved; the loop emits this reason so consumers can prune/retry.'content-filter'— model refused.'pause'— Anthropicpause_turn: a server-side mid-turn pause for very long thinking. The loop continues with a synthetic "Please continue." user message rather than terminating; consumers see the pause via this finish reason on the prior assistant turn.'error'— provider classified the turn as failed.'other'— unknown / unmapped.
Re-exports#
These names are documented on the entry point that owns them.