README
ZigAI
Build agents in Zig. Bring the model you want.
ZigAI is a provider-independent agent framework with native and
OpenAI-compatible provider clients. It gives you one small agent loop:
prompt -> model -> tool calls -> tool results -> final answer
There is no hidden graph. Providers handle wire formats; the agent handles
the conversation.
Key features
- Typed: tools, output, workflows, and settings are Zig types. Schemas
are derived from your structs; invalid data fails before network I/O. - Provider-independent: one agent API across OpenAI, Anthropic, Google,
and twenty more providers. Change the provider; keep the agent and tools. - Explicit: every allocation takes an allocator, every result has one
deinit, every limit has a name. No hidden control flow, no ambient state. - Bounded: untrusted JSON, HTTP bodies, tool results, retries, context,
and queues all have reviewed limits. Overflow is an error, not an OOM. - Complete: streaming, MCP, durable execution, typed graphs, multi-agent,
evaluations, OpenTelemetry, and a production CLI - all under one policy for
ownership, cancellation, and security.
Requirements
Zig 0.16.0. Linux x86_64, Apple Silicon macOS, and Windows x86_64 are the
supported targets. See the compatibility policy.
Installation
zig fetch --save git+https://github.com/Kludex/zigai
Example
A complete agent with a typed tool:
const std = @import("std");
const zigai = @import("zigai");
const WeatherArgs = struct {
city: []const u8,
};
const Weather = struct {
temperature_c: i32,
};
fn weather(args: WeatherArgs) !Weather {
_ = args;
return .{ .temperature_c = 31 };
}
pub fn main(init: std.process.Init) !void {
const key = init.environ_map.get("OPENAI_API_KEY") orelse
return error.MissingApiKey;
var http = zigai.transport.HttpTransport.init(init.gpa, init.io);
defer http.deinit();
var provider = zigai.providers.openai.Provider.init(key, http.transport());
var client = zigai.providers.openai.Client{
.model_name = "gpt-5-mini",
.provider = provider.provider(),
};
const tools = [_]zigai.Tool{
zigai.reflect.tool(
"weather",
"Get the current weather for a city.",
weather,
),
};
var result = try (zigai.Agent{
.model = client.model(),
.tools = &tools,
.system_prompt = "Be concise.",
.io = init.io,
}).run(init.gpa, "What is the weather in Madrid?");
defer result.deinit();
std.debug.print("{s}\n", .{result.output});
}
reflect.tool derives the JSON Schema from WeatherArgs, decodes the
model's arguments, calls the function, and encodes the result. The model
retries invalid arguments; you never parse them yourself.
Want typed output instead of text? Ask for it:
var result = try agent.runTyped(Weather, allocator, "Weather in Madrid?");
defer result.deinit();
std.debug.print("{d} C\n", .{result.output.temperature_c});
Want a different provider? Change two lines:
var provider = zigai.providers.anthropic.Provider.init(key, http.transport());
var client = zigai.providers.anthropic.Client{
.model_name = "claude-sonnet-4-5",
.provider = provider.provider(),
};
The agent, tools, and everything else stay the same.
Documentation
The complete documentation lives at
kludex.github.io/zigai.
Feature guides:
- Agents - the loop, instructions, history, context
budgets, model routing and settings, deadlines - Tools - typed tools, toolsets, policies, approval,
provider-managed tools - Providers - all 23 providers, discovery, catalogs,
profiles, rich content - Typed output and streaming - structured
output, streaming events, retries and resilience - Capabilities - feature bundles, on-demand loading,
harness, execution environments, memory, planning - MCP - client, server, transports, tasks, authorization
- Workflows - typed graphs, multi-agent, durable
execution, embeddings, realtime voice, UI protocols - Observability - hooks, diagnostics,
OpenTelemetry, usage and cost - Evaluations - datasets, graders, online evals, CI gating
- Command-line clients - the production CLI and smoke clients
Reference:
- Public API and ownership
- Architecture
- Production guide
- Security
- Errors
- Durable execution
- Agent specifications
- MCP conformance
- Testing
- Compatibility
- Releasing
- API reference:
zig build docs - Runnable examples:
zig build examples
Testing
./scripts/check
./scripts/test-cli
./scripts/coverage # Linux; the gate is 100% of executable lines
Provider tests replay checked-in YAML cassettes recorded from real APIs, so
CI exercises the real agent, adapters, tool loop, and error paths without
calling paid endpoints. See Testing.
Security
Hosted endpoints use HTTPS-only URL validation by default. Local names,
non-public IPs, embedded URL credentials, and redirects are rejected unless
the application opts in. Authentication headers are recognized as sensitive
and never reach telemetry, diagnostics, or error observers. See
Security and SECURITY.md.
License
ZigAI is licensed under the MIT License.