A local workbench for building, running and debugging AI agents.
One binary, one SQLite file, an embedded UI. See exactly what the model saw on each turn, replay any generation, fork any turn, approve tools in a real sandbox. Built on a Go SDK you can also embed.
Get started · What you get · Workbench manual · SDK docs · Examples
-
Get the binary. From Releases: download the archive for your OS and CPU (macOS, Linux, Windows; amd64, arm64) and extract it — the
agents-serverbinary is at the top level. For example, on an Apple-silicon Mac with the GitHub CLI:gh release download --repo zzir/agents-go --pattern '*_darwin_arm64.tar.gz' tar xzf agents-server_*_darwin_arm64.tar.gz
(A browser download on macOS is quarantined and Gatekeeper refuses the unsigned binary;
xattr -d com.apple.quarantine ./agents-serverclears it.) Or build from source — Go 1.26+ and npm, the UI is compiled into the binary:git clone https://github.com/zzir/agents-go && cd agents-go/cmd/agents-server make build
-
Run it.
./agents-server
It listens on
http://127.0.0.1:9527and prints an auth token at startup; paste the token into the login screen. State lives indata.dbin the directory you ran it from (--db); skills and file tools use--workspace(default.). All flags: manual. -
Add a provider, create an agent, chat. Settings → Providers: an OpenAI or Anthropic API key, or sign in with ChatGPT. Settings → Agents: name, model, instructions, tools. New Chat.
- Zero infrastructure. One process and one SQLite file hold the agents, sessions, traces, approvals and tasks. Nothing else to run.
- The transcript is the truth. A session is an append-only tree: every turn is persisted as it completes, so a cancelled or failed run keeps what finished and a paused run survives a restart. Regenerate a turn, or fork any turn into a new session; branches stay visible and switchable.
- Context lens. What the model actually receives — instructions, global system prompt, memories, skills index, tools by source, conversation — with the token cost of each, how much of the window is in use, cache hits, growth per call, and how far to the next auto-compaction. Compact on demand.
- Traces without a backend. Agent / generation / tool / sandbox / handoff / guardrail spans with tokens and latency, in a panel beside the conversation. No collector to run.
- Replay any generation. Re-run a traced model call with a different prompt, model, settings or tools — streaming, with a diff against the original and the attempts kept side by side. No session is touched.
- Real sandboxes behind an approval gate. Docker, SSH or local; the model
reads and edits files (
apply_patch) and runs commands; approve a command once, trust that command, or trust the session; interactive terminals into a Docker or SSH sandbox, in the browser. - Background tasks, workflows, triggers.
spawn_tasksub-agents that outlive the turn and wake the parent when done (a failed one resumes where it stopped); fixed step sequences as workflows, started by the model, by hand, by cron, or by a signed webhook — and, for an agent you opt in, authored from the chat, each save reviewed and approved in the conversation. - The configuration surface. MCP servers (stdio and streamable HTTP, with OAuth), Agent Skills, memories, guardrails, per-model provider routes.
- Providers. OpenAI Responses API (API key or ChatGPT sign-in), Anthropic Messages API, or any Responses-compatible endpoint by base URL.
Look at what the model saw — the transcript, the Trace panel, the Context lens. Change something — the prompt, tools or model in Settings, or the traced request itself in Replay. Re-run — Replay for one call with no side effects, Regenerate for the last turn, fork to branch from any earlier turn. Compare — the Replay diff, or two forks side by side.
The workbench is a Go program on top of the agents package. Anything it does
you can do from your own code:
go get github.com/zzir/agents-gopackage main
import (
"context"
"fmt"
"github.com/zzir/agents-go/agents"
"github.com/zzir/agents-go/models/openai"
)
func main() {
agent := &agents.Agent{
Name: "assistant",
Instructions: agents.StaticInstructions("You are a helpful assistant."),
Model: "gpt-4o",
}
res, err := agents.RunSync(context.Background(), agent, "Hello!", agents.RunOptions{
// Provider reads OPENAI_API_KEY.
Model: agents.ModelOptions{Provider: openai.NewProvider()},
})
if err != nil {
panic(err)
}
fmt.Println(res.FinalOutputString())
}The Quickstart continues from here — handoffs, guardrails, typed tools, structured output, streaming, approvals. By topic:
- Tools — typed function tools (the argument struct becomes the JSON schema), agents-as-tools, multimodal output, per-tool approval
- Handoffs, Guardrails, Human-in-the-loop — a paused run serializes to JSON and resumes in another process
- Sessions — append-only entries, branching, crash recovery, compaction; in-memory, JSONL, SQLite/Postgres or OpenAI server-side
- Streaming — a run is a range-able iterator; steer it or queue follow-ups mid-run
- Models — OpenAI Responses and Anthropic Messages providers; retry, fallback and routing decorators; middleware around a whole run
- MCP, Sandboxes, Skills,
Tracing (OpenTelemetry via
tracing/otel), Background tasks, Testing —agentstestscripts the model, so agents are tested without a key
The core is one small module; MCP, the Docker/SSH sandboxes, SQL sessions, skills and the Anthropic provider are opt-in submodules (packages). Behavior is specified, not inherited: the SDK started as a port of the OpenAI Agents SDK and now evolves on its own — see Architecture, the feature reference, and Coming from Python?.
Today the workbench runs the agents you configure in it; a program written against the SDK runs on its own, with the SDK's session stores and tracing exporters.
Nearly every SDK capability has a runnable example under examples/:
export OPENAI_API_KEY=sk-...
go run ./examples/hello # minimal agent
go run ./examples/handoffs # triage agent → specialists
go run ./examples/hitl # pause, approve, resumeSee docs/examples.md for all of them.
