core-agent

module
v2.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: Apache-2.0

README

core-agent

A production-grade Go substrate for multi-turn LLM agents, built on the Google Agent Development Kit. Ships the wiring — providers, MCP, skills, permissions, durable sessions, remote attach, an in-process Bubble Tea TUI, and a headless CLI — so downstream projects can focus on their own tools and product logic.

📚 Full documentation: go-steer.github.io/core-agent

CI Docs License Go Reference Release


Features

Runtime

  • Multi-turn conversation via ADK's runner.Runner; parallel tool-call dispatch.
  • In-process Bubble Tea TUI as the default TTY surface; --no-tui line REPL fallback; slim build (-tags no_tui) drops the TUI tree entirely.
  • agent.RunAutonomous for unattended workers with turn / token / cost / wallclock budgets and model-driven termination; ResumeAutonomous picks up from a durable checkpoint after a crash.
  • Long-session survivability: automatic post-turn compaction at ~85% context utilization, subtasks with agentic_* tool wrappers that keep bulk tool output out of the parent's context, and task-boundary checkpoints via mark_task_done. See Context management.

Providers

  • Gemini API (GEMINI_API_KEY / GOOGLE_API_KEY) and Vertex AI (ADC + GOOGLE_CLOUD_PROJECT) with server-side GoogleSearch and URLContext wired up.
  • Anthropic Claude via api.anthropic.com (ANTHROPIC_API_KEY) and via Vertex AI (ADC + ANTHROPIC_VERTEX_PROJECT_ID) as a native model.LLM adapter.
  • Mock providers for credential-free testing: --provider=echo and --provider=scripted --script=path.jsonl; --record-to=path.jsonl captures any real session for later replay.

Instructions, tools, MCP, skills

  • AGENTS.md primary + AGENTS.d/*.md overlay directory + @include <path> directive for composable, multi-file system instructions; both user (~/.core-agent/) and project scope, with CLAUDE.md / GEMINI.md fallbacks.
  • Built-in tool catalog covering files (read_file, read_many_files, write_file, edit_file, delete_file, stat, list_dir), search (glob, grep), data + network (json_query, fetch_url), shell (bash), planning (todo, opt-in record_plan), and interactive prompting (opt-in ask_user). Disable the whole suite with --no-builtin-tools or specific entries with --disable-tools=bash,write_file.
  • MCP servers declared in .agents/mcp.json; stdio and Streamable HTTP transports (including remote MCP with Google OAuth); tools are namespaced (<server>_<tool>) and route through the permission gate.
  • Claude-compatible skills auto-discovered from .agents/skills/<name>/SKILL.md (project) and ~/.core-agent/skills/ (user-global).

Permissions

  • ask / allow / yolo modes with pattern-based allow/deny lists, path-scope enforcement on file tools, URL-scope allowlist for fetch_url, and a non-overridable bash denylist that catches rm -rf /-class mistakes.
  • Plan-first enforcement (permissions.RequirePlanArtifact + record_plan tool + /replan slash): denies mutating tool calls until the model has recorded a plan for the current turn — turns "research → approve → execute" from a prompt convention into a substrate primitive.
  • Pluggable Prompter interface so the same gate works in a TTY, headless (--ask=auto), the in-process TUI, or a custom web frontend.

Persistence + observability

  • Durable sessions and audit log via eventlog.Open(...) — SQLite (pure-Go, CGO-free), Postgres, or MySQL — with monotonic seq, Since(seq) replay, Watch(seq) live-tail, and a session lock for crash-safe multi-process resume.
  • Opt-in OpenTelemetry export (console / OTLP); off by default so a fresh invocation makes zero outbound calls beyond the model.
  • Per-model token + cost tracking with layered pricing (daily LiteLLM refresh, per-config overrides, longest-prefix fallback).

Remote attach + operator surface

  • Attach API: HTTP + Server-Sent Events live-tail + POST /sessions/<sid>/inject + /wake for headless agents, over mTLS + bearer auth. Read-only GET /sessions/<sid>/{tools,agents,status} and GET /permissions/snapshot endpoints for operator dashboards.
  • Remote TUI client (core-agent-tui, separately-versioned binary): thin bubble-tea shell on go-steer/core-tui that attaches to any daemon over the attach API — full slash parity with the in-process TUI (/stats, /context, /compact, /done, /subagent, /btw, /memory, /skills, /mcp, /pricing, /perms, /allow, /deny, /reload), per-turn cost footer, live tool-approval modals over HTTP, mid-turn /inject, session switcher.
  • Multi-session daemon: one core-agent daemon serves many concurrent sessions with per-caller identity, ACL (Owner/Viewers/Contributors), permission grants, instruction overlays, and audit attribution. Sessions survive daemon restarts (config change, image upgrade, K8s pod replacement) — a reconnecting TUI resumes transparently. Opt-in via multi_session.enabled: true.
  • Attach-config (.agents/config.json attach.* block + ${ENV_VAR} expansion) so a K8s ConfigMap can replace half a dozen CLI flags.
  • Peer registration for hub-and-spoke fleet discovery on top of attach.
  • Agent-card discovery: opt-in /.well-known/agent-card.json endpoint describing name, description, skills, and required auth in the A2A AgentCard shape so agent registries can index the binary.

Subagents

  • In-process: agent.WithSubagents([]*Agent) for synchronous delegation; agent.NewBackgroundAgentManager + spawn_agent / list_agents / check_agent / stop_agent for background subagents the model spawns at runtime.
  • Remote: agent.NewSpawnRemoteAgentTool with a consumer-supplied RemoteAgentSpawner for out-of-process spawning (gRPC / K8s Jobs / Cloud Run).
  • Subagent events stream into the parent's audit log under a Branch label so the trail stays unified.

Kubernetes triage sidecar (v2.6+)

  • cmd/k8s-event-watcher/ — client-go informer that watches Kubernetes Events, filters + dedupes, and injects matched incidents into per-incident sessions on a core-agent daemon. Pairs with the bundled triage skill to drive diagnose → fix → verify loops via the GKE MCP, gated by plan-first. See examples/gke-troubleshoot-agent/.

Optional adapters

  • extras/scion-agent/ — runs core-agent inside Scion's container runtime with lifecycle status emission and a sciontool_status tool.
  • extras/ax-agent/ (on the axplore branch) — AX gRPC remote-agent packaging.

Install

CLI (Go toolchain, requires Go 1.26+):

go install github.com/go-steer/core-agent/v2/cmd/core-agent@latest

Pre-built binary (Sigstore-signed; linux/darwin × amd64/arm64):

TAG=$(gh release view --repo go-steer/core-agent --json tagName -q .tagName)
OS=$(uname -s | tr A-Z a-z)
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
gh release download "$TAG" --repo go-steer/core-agent \
  --pattern "core-agent_${TAG#v}_${OS}_${ARCH}.tar.gz"
tar xzf "core-agent_${TAG#v}_${OS}_${ARCH}.tar.gz"
./core-agent --version

core-agent-tui archives use the same naming pattern. Verification details are in each release's notes footer.

Container images (multi-arch amd64 + arm64; distroless static; Sigstore-signed):

docker pull ghcr.io/go-steer/core-agent:latest        # daemon + in-process TUI
docker pull ghcr.io/go-steer/core-agent-slim:latest   # headless daemon, ~5MB smaller
docker pull ghcr.io/go-steer/core-agent-tui:latest    # remote TUI client only
docker pull ghcr.io/go-steer/k8s-event-watcher:latest # K8s event-triage sidecar

Floating tags: :latest, :X.Y.Z, :X.Y, :X (semver, no v prefix), :main, :main-<sha>.

Library:

go get github.com/go-steer/core-agent/v2

Module path note (post-v2.7): the module path carries the /v2 suffix required by Go's SIVE rule. Consumers upgrading from v2.6 or earlier need to rewrite imports: github.com/go-steer/core-agent/pkg/...github.com/go-steer/core-agent/v2/pkg/.... Container images and source builds were never affected; only go install ...@v2.X.Y and go get require the migration. Pre-fix tags (v2.0.0 through v2.7.0-dev.4) can't be go installed — use @main, a pinned commit SHA, container images, or a source build for those.

Container variants at a glance
Image What it is When to pull it
core-agent Full daemon: multi-session runtime + in-process Bubble Tea TUI + remote-attach API. Default target.
core-agent-slim Same daemon, built -tags no_tui. ~5MB smaller. Distroless K8s pods where the TUI is dead weight.
core-agent-tui Remote TUI client only. Connects to a daemon over the attach API. Operator workstations attaching to a remote daemon.
k8s-event-watcher Sidecar that watches Kubernetes Events, dedupes, and injects matched ones into a daemon. GKE / K8s troubleshooting agents.

Quick start — CLI

# Gemini API key (either variable works)
GEMINI_API_KEY=... core-agent -p "what's 2+2?"

# Anthropic API key
ANTHROPIC_API_KEY=... core-agent --provider anthropic -p "what's 2+2?"

# Multi-turn TUI (bare invocation; conversation persists across turns)
core-agent

Vertex AI (both Gemini and Claude), scripted providers, .agents/config.json defaults, and the full CLI flag reference live in Getting started.

Quick start — library

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/go-steer/core-agent/v2/pkg/agent"
    "github.com/go-steer/core-agent/v2/pkg/config"
    "github.com/go-steer/core-agent/v2/pkg/models"
    _ "github.com/go-steer/core-agent/v2/pkg/models/gemini"
)

func main() {
    cfg := config.DefaultConfig()
    cfg.Model.Provider = config.ProviderGemini

    provider, err := models.Resolve(cfg)
    if err != nil { log.Fatal(err) }

    ctx := context.Background()
    m, err := provider.Model(ctx, cfg.Model.Name)
    if err != nil { log.Fatal(err) }

    a, err := agent.New(m, agent.WithInstruction("Be concise."))
    if err != nil { log.Fatal(err) }

    for event, err := range a.Run(ctx, "What is the capital of France?") {
        if err != nil { log.Fatal(err) }
        if event.Content == nil { continue }
        for _, p := range event.Content.Parts {
            if p.Text != "" && event.Partial {
                fmt.Print(p.Text)
            }
        }
    }
    fmt.Println()
}

Fuller examples in examples/ — basic, with-tools, streaming, autonomous, autonomous-resume, with-subagent, background-monitor, scheduled-monitor, replay, plan-first, cloud-run-deploy, gke-*.


Documentation

The site is built with Astro and Starlight; sources live in docs/site/.


Project layout

core-agent/
├── pkg/                    # public library surface (v1 stability)
│   ├── agent/              # ADK llmagent + runner wrapper; Option pattern
│   ├── attach/             # HTTP + SSE + auth + multi-session daemon
│   ├── config/             # .agents/config.json schema + discovery
│   ├── digest/             # structural digest system for tool responses
│   ├── eventlog/           # durable session.Service + audit/replay stream
│   ├── instruction/        # AGENTS.md / CLAUDE.md / GEMINI.md loader
│   ├── mcp/                # mcp.json schema, stdio/HTTP server lifecycle
│   ├── models/             # provider registry + gemini/ + anthropic/ + mock/
│   ├── permissions/        # ask/allow/yolo gate + denylist + path scope
│   ├── recording/          # LLM-wire recorder for offline replay
│   ├── runner/             # headless (one-shot) + REPL/TUI drivers
│   ├── session/            # JSON transcript persistence
│   ├── skills/             # SKILL.md discovery → ADK skilltoolset
│   ├── telemetry/          # OTEL exporter setup
│   ├── tools/              # built-in tools + GateToolset wrapper
│   └── usage/              # per-turn token + cost tracker
├── cmd/
│   ├── core-agent/         # daemon + CLI + in-process TUI
│   ├── core-agent-tui/     # remote TUI client
│   └── k8s-event-watcher/  # K8s event-triage sidecar
├── extras/scion-agent/     # opt-in Scion runtime adapter
├── examples/               # 15+ worked examples
├── docs/                   # DESIGN.md, release-process.md, Astro site
├── SKILLS/                 # bundled meta-skills (cli-setup, autonomous-setup, library-embedding)
└── dev/                    # build/test/lint/release tooling

The Provider interface is the extension point — register your own model backend with models.Register("name", constructor) and the rest of the stack picks it up.


Project conventions

  • .agents/ directory — walked up from the working directory like .git. Holds config.json, mcp.json, skills/<name>/SKILL.md, and per-session JSON transcripts.
  • AGENTS.md — project-level system-instruction prefix. CLAUDE.md and GEMINI.md are picked up as fallbacks for repos that already have one.
  • ~/.<binary>/sessions.db — durable session storage when --session-db is set. The binary name is derived from os.Executable() so core-agent, adapters, and forks each get their own directory. Override with --session-db-path.

Contributing

  • Run dev/tools/ci before opening a PR — same checks GitHub Actions runs (vet, build, lint, mod-tidy, test, vuln scan), in fast-fail order. See dev/README.md.
  • Every source file carries the Apache 2.0 header. goheader in dev/tools/lint-go enforces this for .go; run dev/tools/add-license-headers for new shell / YAML / Python files.
  • The library is meant to stay narrow. Downstream-specific tools, flags, and slash commands belong in consumer projects.

License

Apache-2.0. See LICENSE.

Directories

Path Synopsis
cmd
core-agent command
Command core-agent is a thin CLI wrapper around the core-agent library.
Command core-agent is a thin CLI wrapper around the core-agent library.
core-agent-tui command
Command core-agent-tui is the operator-facing TUI consumer of attach-mode — the remote client for an agent running elsewhere (on a workstation, in a K8s pod, or as a peer-registered fleet member).
Command core-agent-tui is the operator-facing TUI consumer of attach-mode — the remote client for an agent running elsewhere (on a workstation, in a K8s pod, or as a peer-registered fleet member).
k8s-event-watcher command
Command k8s-event-watcher is the v2.6 semi-autonomous-triage sidecar.
Command k8s-event-watcher is the v2.6 semi-autonomous-triage sidecar.
dev
parallel-probe command
Diagnostic: measure how often the model emits multiple tool calls per assistant turn.
Diagnostic: measure how often the model emits multiple tool calls per assistant turn.
regen-builtin-pricing command
Generator for internal/pricing/builtin.go.
Generator for internal/pricing/builtin.go.
smoke/cmd/inspect-grounding command
Command inspect-grounding dumps every agent_eventlog row whose author starts with "gemini/" from a SQLite eventlog database.
Command inspect-grounding dumps every agent_eventlog row whose author starts with "gemini/" from a SQLite eventlog database.
uat/scheduled-monitor command
UAT driver for the scheduled-monitoring feature (docs/scheduled-monitoring-design.md).
UAT driver for the scheduled-monitoring feature (docs/scheduled-monitoring-design.md).
examples
autonomous command
Example: drive an agent through agent.RunAutonomous end-to-end with no LLM credentials.
Example: drive an agent through agent.RunAutonomous end-to-end with no LLM credentials.
autonomous-handle command
Example: drive an autonomous run via the AutonomousHandle API.
Example: drive an autonomous run via the AutonomousHandle API.
autonomous-resume command
Example: drive an agent through agent.RunAutonomous, simulate a crash via a tight max-turns budget, then continue the run with agent.ResumeAutonomous against the same SQLite event log.
Example: drive an agent through agent.RunAutonomous, simulate a crash via a tight max-turns budget, then continue the run with agent.ResumeAutonomous against the same SQLite event log.
background-monitor command
Example: wire a BackgroundAgentManager and demonstrate the in-process spawn pathway end-to-end with no LLM credentials.
Example: wire a BackgroundAgentManager and demonstrate the in-process spawn pathway end-to-end with no LLM credentials.
basic command
Example: minimal multi-turn agent using the core-agent library directly (no CLI).
Example: minimal multi-turn agent using the core-agent library directly (no CLI).
replay command
Example: drive the agent loop offline by replaying a recorded JSONL transcript through the mock "scripted" provider — no LLM credentials required.
Example: drive the agent loop offline by replaying a recorded JSONL transcript through the mock "scripted" provider — no LLM credentials required.
scheduled-monitor command
Example: the supervision-tree topology from docs/scheduled-monitoring-design.md, end-to-end with no LLM credentials.
Example: the supervision-tree topology from docs/scheduled-monitoring-design.md, end-to-end with no LLM credentials.
streaming command
Example: drive the agent with the standard built-in tools (read_file, list_dir, bash, etc.) and render the response as an interactive chat session via runner.WriteEvents.
Example: drive the agent with the standard built-in tools (read_file, list_dir, bash, etc.) and render the response as an interactive chat session via runner.WriteEvents.
with-subagent command
Example: drive a parent agent with a subagent end-to-end with no LLM credentials.
Example: drive a parent agent with a subagent end-to-end with no LLM credentials.
with-tools command
Example: an agent with one custom tool, MCP servers loaded from .agents/mcp.json (if present), and SKILL.md skills from .agents/skills/ (if any).
Example: an agent with one custom tool, MCP servers loaded from .agents/mcp.json (if present), and SKILL.md skills from .agents/skills/ (if any).
internal
attachclient
Package attachclient is the shared client for attach-mode endpoints, used by both `core-agent attach`/`ls` (in cmd/core-agent) and `core-agent-tui` (in cmd/core-agent-tui).
Package attachclient is the shared client for attach-mode endpoints, used by both `core-agent attach`/`ls` (in cmd/core-agent) and `core-agent-tui` (in cmd/core-agent-tui).
coretuiremote
Package coretuiremote adapts a remote core-agent (reached over the pkg/attach HTTP+SSE protocol via internal/attachclient) into a go-steer/core-tui Agent.
Package coretuiremote adapts a remote core-agent (reached over the pkg/attach HTTP+SSE protocol via internal/attachclient) into a go-steer/core-tui Agent.
pricing
Package pricing resolves a model's per-million-token rates across a layered set of sources so usage costs stay accurate as new models ship and operators add overrides.
Package pricing resolves a model's per-million-token rates across a layered set of sources so usage costs stay accurate as new models ship and operators add overrides.
testutil
Package testutil provides shared test helpers for Cogo, most notably FakeModel — a deterministic implementation of google.golang.org/adk/model.LLM that lets us drive end-to-end agent tests without burning real tokens.
Package testutil provides shared test helpers for Cogo, most notably FakeModel — a deterministic implementation of google.golang.org/adk/model.LLM that lets us drive end-to-end agent tests without burning real tokens.
version
Package version centralizes build-identity reporting for both cmd/core-agent and cmd/core-agent-tui.
Package version centralizes build-identity reporting for both cmd/core-agent and cmd/core-agent-tui.
vertexcache
Package vertexcache owns the lifecycle of a single Vertex explicit context cache — Create at agent startup, Refresh on TTL pressure, Delete on session unregister.
Package vertexcache owns the lifecycle of a single Vertex explicit context cache — Create at agent startup, Refresh on TTL pressure, Delete on session unregister.
webui
Package webui embeds a pinned release of the mast-web operator UI (github.com/go-steer/mast-web) so the agent binary can serve it at /ui/* on its attach listener when the --ui flag is set.
Package webui embeds a pinned release of the mast-web operator UI (github.com/go-steer/mast-web) so the agent binary can serve it at /ui/* on its attach listener when the --ui flag is set.
pkg
agent
Package agent wraps the Google ADK runner with sensible defaults (streaming mode, in-memory session service, app name) so consumers hit the same shape regardless of whether they're driving the agent from a one-shot CLI, a REPL, or an HTTP handler.
Package agent wraps the Google ADK runner with sensible defaults (streaming mode, in-memory session service, app name) so consumers hit the same shape regardless of whether they're driving the agent from a one-shot CLI, a REPL, or an HTTP handler.
agentenv
Package agentenv parses the optional .agents/env.yaml (or .env.json) manifest and produces a Resolver that agent-bundle loaders can use to interpolate ${env:VAR} references in AGENTS.md, skill files, and mcp.json values.
Package agentenv parses the optional .agents/env.yaml (or .env.json) manifest and produces a Resolver that agent-bundle loaders can use to interpolate ${env:VAR} references in AGENTS.md, skill files, and mcp.json values.
attach
Package attach implements live-tail + inject over HTTP/SSE for headless core-agent deployments.
Package attach implements live-tail + inject over HTTP/SSE for headless core-agent deployments.
auth
Package auth defines the per-caller identity primitive used by the multi-session attach layer.
Package auth defines the per-caller identity primitive used by the multi-session attach layer.
config
Package config defines the on-disk schema for `.agents/config.json` and the rules for discovering, parsing, and merging it with built-in defaults.
Package config defines the on-disk schema for `.agents/config.json` and the rules for discovering, parsing, and merging it with built-in defaults.
digest
Package digest consolidates the digesting primitives core-agent uses to keep large tool responses out of the parent context.
Package digest consolidates the digesting primitives core-agent uses to keep large tool responses out of the parent context.
eventlog
Package eventlog is the durable, append-only audit log that backs agent.Agent's session.Service.
Package eventlog is the durable, append-only audit log that backs agent.Agent's session.Service.
hooks
Package hooks dispatches shell commands on agent-side event boundaries.
Package hooks dispatches shell commands on agent-side event boundaries.
instruction
Package instruction loads project + user "agent memory" files (typically AGENTS.md) into the system prompt.
Package instruction loads project + user "agent memory" files (typically AGENTS.md) into the system prompt.
mcp
Package mcp wires user-configured Model Context Protocol servers into the agent loop.
Package mcp wires user-configured Model Context Protocol servers into the agent loop.
models
Package models is the adapter layer between core-agent's configuration and concrete LLM backends.
Package models is the adapter layer between core-agent's configuration and concrete LLM backends.
models/anthropic
Package anthropic implements models.Provider for Anthropic / Claude.
Package anthropic implements models.Provider for Anthropic / Claude.
models/gemini
Package gemini implements models.Provider for the Gemini family, covering both the public Gemini API (API-key auth) and Vertex AI (Application Default Credentials + GCP project).
Package gemini implements models.Provider for the Gemini family, covering both the public Gemini API (API-key auth) and Vertex AI (Application Default Credentials + GCP project).
models/mock
Package mock ships two credential-free LLM providers and a recording wrapper that pair for offline testing of agent flows:
Package mock ships two credential-free LLM providers and a recording wrapper that pair for offline testing of agent flows:
modeltier
Package modeltier classifies LLM model IDs into capability tiers (frontier / mid / small) used to tune behavior whose right setting depends on how powerfully the model reasons.
Package modeltier classifies LLM model IDs into capability tiers (frontier / mid / small) used to tune behavior whose right setting depends on how powerfully the model reasons.
permissions
Package permissions implements the central permission gate that decides whether each tool invocation may proceed.
Package permissions implements the central permission gate that decides whether each tool invocation may proceed.
recording
Package recording wraps an adkmodel.LLM with a JSONL transcript recorder for offline observability and scripted-replay testing.
Package recording wraps an adkmodel.LLM with a JSONL transcript recorder for offline observability and scripted-replay testing.
runner
Package runner drives the agent through a real conversation — either a single one-shot prompt (Headless) or a multi-turn stdin REPL (REPL).
Package runner drives the agent through a real conversation — either a single one-shot prompt (Headless) or a multi-turn stdin REPL (REPL).
session
Package session writes session transcripts to disk on exit.
Package session writes session transcripts to disk on exit.
skills
Package skills loads SKILL.md bundles from .agents/skills/<name>/ and exposes them as an ADK Toolset the agent can invoke.
Package skills loads SKILL.md bundles from .agents/skills/<name>/ and exposes them as an ADK Toolset the agent can invoke.
telemetry
Package telemetry initializes OpenTelemetry for the agent loop.
Package telemetry initializes OpenTelemetry for the agent loop.
tools
Package tools provides ADK-side helpers for wiring tools into the agent.
Package tools provides ADK-side helpers for wiring tools into the agent.
usage
Package usage tracks token + cost accounting for the agent loop.
Package usage tracks token + cost accounting for the agent loop.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL