- 01 Model + provider selection
- 02 Coding-agent system prompt
- 03 Bubble Tea terminal UI
- 04 Slash commands + UX policy
- 05 Interactive and one-shot modes
Axon | Go Agent Runtime
Build the agent.
Don’t rebuild the runtime.
Axon is the execution layer underneath Cortex, a real terminal coding agent. It owns the long-running loop between models, tools, sessions, context, processes, and events — while your product stays in control of behavior and UX.
go get github.com/atakang7/axon/v2Cortex is not a demo for Axon.
It is a product built on Axon.
The cleanest way to understand the runtime is to look at what Cortex does not implement. Cortex owns the coding-agent product. Axon owns the generic execution machinery underneath it.
- 01 Model / tool turn loop
- 02 Session persistence + undo
- 03 Context projection + pruning
- 04 Foreground + background execution
- 05 Streaming + retries + events
Cortex wires the runtime once.
Its newAgent function converts product configuration into an axon.Config. The interactive TUI and non-interactive CLI both go through that same constructor, so the product cannot quietly grow a second agent loop.
return axon.New(axon.Config{
Model: model,
SystemPrompt: cfg.SystemPrompt,
MCPServers: servers,
OnEvent: onEvent,
Settings: settings,
Pruner: prunerModel,
})Three layers. One direction.
Product intent flows down. Runtime events flow back up. Axon is the seam that keeps those concerns from collapsing into one codebase.
New, Step, Run, Interrupt, Reset, Undo, runtime controls.Step() is the engine room.
One user message can become many model calls and many tool executions. Axon owns that continuation until the model finally returns with no more tool calls.
model, err := settings.NewClient("openrouter", "deepseek/deepseek-v3.2")
if err != nil { log.Fatal(err) }
agent, err := axon.New(axon.Config{
Model: model,
SystemPrompt: "You are a careful coding agent.",
OnEvent: render,
})
if err != nil { log.Fatal(err) }
defer agent.Close()
result, err := agent.Step(ctx, "Find and fix the failing test.")Step itself or hand Axon an input function through Run.Seven tools. Replace any of them.
Axon ships the mundane capabilities coding agents repeatedly need. Exclude a built-in to free its name, then supply your own implementation behind the same tool surface.
readslice · fullRead files or list directories. Binary-aware, byte-capped, line-addressable.
write4 edit modesAtomic tmp + rename writes. Every edit is recorded so agent.Undo() can restore it.
execfg · bgRun sh -lc commands with timeout control or detach long-lived processes into managed groups.
bash_outputdeltaPoll only output produced since the previous read, with offset and file-identity tracking.
kill_shelllifecycleTerminate a whole process group: SIGTERM, grace period, then SIGKILL when needed.
searchliteral · regexRipgrep-backed workspace search with globs, case control, and bounded results.
taskplan stateRegister, advance, or replan a compact multi-step goal injected into context.
Long-running commands are first-class.
Servers, watchers, network clients, and anything that may hang can leave the foreground turn without leaving Axon’s lifecycle.
execrun_in_background=truebash_1process group + logfilebash_outputread only new byteskill_shellTERM → grace → KILLKeep history. Change the view.
Axon does not rewrite the session to make context smaller. The historical log stays intact; ContextMessages() derives a bounded projection for each model call.
Recency window
Old blocks collapse to one-line breadcrumbs without a model call. Recent active blocks stay complete.
Model-assisted pruner
A cheaper secondary model can park stale blocks. Protected messages and edited-file evidence stay available.
Full history survives
Parking changes the request projection, not the session record. The runtime can still reason from durable history.
200 OK does not always mean “good reply.”
LLM APIs fail in ways ordinary request wrappers do not cover: truncated SSE streams, stalled connections, partial tool-call fragments, retryable statuses, and even tool markup leaked as plain text.
SSE is reassembled, not assumed.
Tool-call fragments are accumulated by index and emitted in stable order when the stream finishes.
Transport and HTTP policy are separate.
retry:
max_attempts: 10
backoff_cap: 60s
on_status: [429, 500, 502, 503, 504]EOFs, resets, DNS failures, and timeouts are transport failures. HTTP statuses follow explicit policy.
Success responses can still be invalid.
Axon refuses to silently end a turn on provider markup that should have been parsed as a tool call.
Everything important becomes an event.
Cortex’s terminal is not inside Axon. It subscribes to ordered runtime events, converts them into UI messages, and owns presentation on its own goroutine.
session_startturn_startuser_inputapi_calltokenreasoningtool_arg_deltatool_calltool_resultusageprune_startprune_endturn_endswitch e.Kind {
case axon.KindToken:
fmt.Print(e.Text)
case axon.KindToolCall:
drawTool(e.Tool)
case axon.KindUsage:
updateTokens(e.Usage)
case axon.KindPruneEnd:
updateContext(e.Prune)
}Tools get capabilities, not the Agent.
Built-ins are constructed with narrow interfaces and flat limits. They do not receive the settings object, model credentials, conversation history, or the registry of other tools.
Important: the working directory is routing, not a sandbox. Axon narrows runtime interfaces; OS-level sandboxing remains an embedder decision.
Cortex proves the architecture.
SWE-rebench tests the performance.
The first Axon/Cortex benchmark is intentionally boring: the complete frozen February 2026 SWE-rebench split, one deterministic trajectory per task, the same model family, no web, and hidden PASS / FAIL evaluation.
commit SHAmodelreasoningsystem promptsettingsinstance IDslimitsweb=offThe runtime is the part you should be able to stop thinking about.
Wire one model and one prompt. Then add the pieces your product actually needs: events, a pruner, MCP, custom tools, or a UI.
Cortex is one agent.
Axon is the factory underneath.
A coding agent is only one specialization. Keep Axon’s loop, sessions, context, retries, processes, and events — then change the role, tools, model, and policy to build an expert for a completely different operational domain.
Kubernetes operator
Investigate unhealthy workloads across pods, events, deployments, services, ingress, Helm state, and metrics — then propose or execute a bounded fix.
kubectlhelmprometheusgitcloud APICrashLoopBackOff → inspect events + logs → find bad config → patch manifest → rollout status → verify recovery
Incident responder
Take an alert, gather logs and metrics, follow a runbook, build a timeline, test hypotheses, and drive a reversible mitigation while emitting an audit trail.
PagerDutyGrafanaLokishellrunbooksLatency alert → correlate deploy + traces → isolate failing dependency → rollback → watch SLO recover → write incident summary
Cloud / DevOps engineer
Reason across IaC, CI/CD, cloud inventory, IAM, runtime state, and deployment history without baking those vendor decisions into the agent runtime.
OpenTofuAWS/Azure/GCPGitHubCI/CDcost APIsService needs private S3 access → inspect VPC + IAM → patch IaC → plan → approval → apply → connectivity check
Security analyst
Join scanner findings with repository context, IAM configuration, SBOM data, deployment state, and policy — then turn a finding into a concrete, reviewable change.
Trivy/SBOMIAM APIsgitpolicy engineticketingCritical image CVE → locate deployed versions → find owning Dockerfile → update base → test → rescan → open remediation PR
Database / data operator
Inspect schemas, query plans, replication state, jobs, migrations, and backups while keeping destructive actions behind explicit product-level controls.
SQLmigration CLImetricsbackup APIrunbooksSlow endpoint → inspect query plan → find missing index → generate migration → validate on staging → observe p95 after rollout
Release engineer
Own the mechanical path from a repository state to a verified release: tests, versioning, changelog, artifacts, deployment, smoke checks, and rollback evidence.
gitGitHubCIregistrydeploy APIRelease request → inspect commits → run test matrix → cut version → publish artifact → deploy canary → verify health
Give the model cluster capabilities. Keep the runtime generic.
The Kubernetes knowledge lives in the role and tool descriptions. Cluster access lives inside your tool closures or MCP servers. Axon still only sees ordinary tools and ordinary results, which means the same runtime mechanics used by Cortex can drive a completely different expert.
agent, err := axon.New(axon.Config{
Model: model,
SystemPrompt: kubernetesOperatorPrompt,
Tools: []axon.Tool{
kubectlTool,
helmTool,
prometheusTool,
approvalTool,
},
Pruner: cheapContextModel,
OnEvent: audit,
})approvalTool is your capability gate — for example, read-only by default and explicit approval before mutations.Specialized agents need depth, not a giant framework.
Config.Tools and MCP let you expose exactly the capabilities an expert needs — no more.Axon gives you the execution substrate. Production authorization, approval gates, credentials, sandboxing, and blast-radius controls remain product/tool decisions — exactly where a specialized agent should make them explicit.