extension api: zi table
zi.register_tool(spec)- Register a model-visible tool. See tools.
zi.register_command(spec)- Register an interactive slash command. See commands.
zi.register_provider(name, config)- Register or override a provider claim. See providers.
zi.unregister_provider(name)- Remove this extension's provider claim.
zi.on(event_name, handler)- Register an observer or interceptor handler. See events.
zi.spawn(opts)- Run delegated child zi work through batch JSON mode. See spawn helper.
zi.system(argv, opts?)- Run an argv-style system command through the extension async scheduler. Captures bounded stdout/stderr and returns a structured result.
tools
Tools are definition-first. A tool definition is the unit zi exposes to the model. Tool handlers receive the shared context object.
zi.register_tool(spec) accepts:
name- Required string. The model-visible tool id and collision key.
description- Required string. Human/model-facing description.
parameters- Required table. JSON-schema-like parameter schema; host validation owns whether
executemay run.
execute(params, ctx)- Required function. Runs the tool and returns the terminal tool result. Use context ui api, context state api, or context model and ai api from here as needed.
label- Optional string. UI label. Defaults to
name.
prompt_snippet- Optional string. Prompt metadata for model guidance.
prompt_guidelines- Optional array of strings. Additional prompt guidance bullets.
render_call(args, ctx)- Optional function. Custom call-slot renderer.
render_result(result, ctx)- Optional function. Custom result-slot renderer.
A terminal tool result has this shape:
{
content = {
{ type = "text", text = "..." },
},
details = {}, -- optional open JSON-compatible envelope
is_error = false,
}
Tool names are unique. If a later extension registers a tool with an already-claimed name, the later registration is ignored and zi.register_tool returns false.
commands
zi.register_command(spec) accepts:
name- Required string. Slash command name, without the leading
/.
description- Optional string. Shown in command lists.
handler(args, ctx)- Required function. Runs on the agent thread when the command is invoked.
Example:
return function(zi)
zi.register_command({
name = "hello",
description = "Show a greeting.",
handler = function(args, ctx)
ctx.ui.report({
id = "hello-command",
title = "hello",
body = "hello, " .. (args or "zi"),
transient = true,
})
end,
})
end
Slash command ordering is:
1. built-in interactive commands 2. extension commands 3. prompt-template and skill expansion on command miss 4. input interceptor over surviving prompt text 5. prompt assembly and provider run
Built-ins stay TUI-local when they need immediate UI/session behavior. Extension commands enqueue semantic command work to the agent thread. Command handlers receive the same context object as tools and events.
providers
Providers let extensions add or override visible model/provider choices.
zi.register_provider(name, config) supports:
api- Required for custom provider names. For built-in provider overrides, zi can infer the required API family.
base_url- Required string.
api_key- Optional string.
headers- Optional string map.
models- Optional array of model tables for provider-owned visible models. Built-in provider overrides use the built-in visible catalog.
oauth- Optional OAuth callbacks for provider-owned models where the host has a compatible OAuth template. Supported callback fields are
login,refresh_tokenorrefreshToken, andgetApiKey.
Built-in visible provider names with override support today are:
anthropicopenaiopenrouteropenai-codex
Provider registration changes the host-owned provider/model views. Extensions own claims, not provider runtime pointers or credential persistence. Use before_provider_request for request rewriting, and context model and ai api for model inspection/completions.
events
zi.on(name, handler) registers an observer or interceptor. Handlers receive (event, ctx), where ctx is described in context object.
Observer events are additive and post-commit. Return values are ignored.
Interceptor events run before zi commits an action. Depending on the event family, handlers may replace payloads, cancel the action, or provide event-specific results.
Supported event names include:
session_directory- Startup event for selecting a session directory.
resources_discover- Add resource folders for
lua/,prompts/,skills/,themes/, andagents/.
input- Middleware/cancellable seam over submitted prompt text after slash-command dispatch.
before_agent_start- Event before the final agent prompt/request. May add messages or replace the system prompt.
context- Middleware over message context used for the next provider call.
before_provider_request- Middleware over semantic provider request payload.
agent_start,agent_end- Observe agent run boundaries.
turn_start,turn_end- Observe assistant turn boundaries.
message_start,message_update,message_end,message- Observe transcript/message edges.
message_updateis for streaming assistant deltas.message_endis the raw lifecycle edge.messageis the durable semantic observer, dispatched after session persistence withevent.message.entry_idfor use withctx.session.entry, notes, and labels.
tool_execution_start,tool_execution_update,tool_execution_end- Observe tool execution state.
tool_call- Middleware/cancellable seam over validated tool call input.
tool_result- Middleware seam over final tool result content, details, and error bit before commit.
user_bash- Cancellable/aggregate seam for user-initiated shell execution.
session_start,session_shutdown- Observe session lifecycle.
session_before_switch- Cancellable seam before
/newor/resumereplaces the session.
session_before_fork- Cancellable/aggregate seam before forking from an entry.
session_before_compact,session_compact- Pre/post compaction events.
session_before_tree,session_tree- Pre/post tree navigation events.
model_select- Observe model selection changes.
Interceptors should return only event-specific semantic data. They should not depend on transport structs, TUI state, mailbox state, or provider runtime handles.