Install
$ agentstack add mcp-go-steer-core-agent ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
core-agent
A reusable Go-based agent built on the Google Agent Development Kit.
📚 Full documentation: go-steer.github.io/core-agent
[](https://github.com/go-steer/core-agent/actions/workflows/ci.yml) [](https://go-steer.github.io/core-agent/) [](./LICENSE) [](https://pkg.go.dev/github.com/go-steer/core-agent)
core-agent is the bottom layer for any project that needs a multi-turn LLM agent. It ships the wiring — model providers, MCP servers, skills loading, instruction loading, permission gating, telemetry, transcript persistence — so consuming projects can focus on their own tools and product logic.
> Status: early. APIs may change. The headless CLI works; the library is in active use as the foundation for downstream projects in the go-steer org.
Features
- Multi-turn conversation — backed by ADK's
runner.Runnerwith an in-memory session service that automatically replays history across turns. - Multiple model providers, picked by config or auto-detected from environment:
- Gemini API via
GOOGLE_API_KEYorGEMINI_API_KEY(either is accepted;GEMINI_API_KEYis the one Gemini's own docs and tutorials use). Gemini's built-in Google Search and URL Context tools are wired up by default; Code Execution is one option flip away. - Vertex AI (Gemini) via
GOOGLE_GENAI_USE_VERTEXAI=true+ ADC +GOOGLE_CLOUD_PROJECT— same built-in tools as Gemini API. - Anthropic / Claude via
ANTHROPIC_API_KEY— implemented as a native ADKmodel.LLMadapter (ADK Go ships only Gemini + Apigee out of the box). Claude's server-side Web Search is one option flip away. - Anthropic / Claude via Vertex AI via ADC +
ANTHROPIC_VERTEX_PROJECT_ID+CLOUD_ML_REGION— same adapter, GCP-authed and GCP-billed, no separate Anthropic API key required - Mock providers for credential-free testing —
--provider=echoreturns the user prompt verbatim;--provider=scripted --script=transcript.jsonlreplays a recorded session. Pair with--record-to=path.jsonlagainst any provider to capture a transcript for later replay. - AGENTS.md instruction loading — system prompt prefix is assembled from
~/.core-agent/AGENTS.mdand the project'sAGENTS.md(withCLAUDE.md/GEMINI.mdfallbacks), preserving the agent.md convention plus the fallback names other agent tools have adopted. - MCP servers — declarative
.agents/mcp.json; stdio and Streamable HTTP transports; tools are namespaced (_) and pass through the permission gate. - Claude-compatible skills — drop a
SKILL.mdbundle into.agents/skills//and the agent can invoke it on demand via ADK'sskilltoolset. - Built-in tool suite —
read_file,write_file,edit_file,list_dir,glob,grep,bash,todo. Wired up by default in the bundled CLI; opt-out via--no-builtin-toolsfor the whole suite, or--disable-tools=bash,write_file(ortools.disablein config) for specific entries. All tools route through the permission gate. - Permission gate — ask / allow / yolo modes, per-tool allow- and deny-list patterns, path-scope checks for file tools, and a built-in bash denylist that's non-overridable. In the bundled CLI,
askmode prompts the user interactively (y/s/t/a/N) when stdin is a TTY;--yolobypasses the gate entirely for headless use. - Server-side built-in observability — Gemini's
GoogleSearchactivity surfaces in the chat-style stdout (↪ google_search: query: ...,↪ google_search: —) and as queryablegemini/google_search-authored rows in the eventlog when--session-dbis enabled. Same↪namespace reserved for Anthropic's server-side tools when they land. - Telemetry — opt-in OpenTelemetry export (console / OTLP); off by default so a fresh invocation makes zero outbound calls.
- Headless CLI —
core-agent -p "prompt"for one-shot use; barecore-agentdrops into a stdin REPL with conversation history preserved across turns. - Autonomous-run driver —
agent.RunAutonomousfor unattended multi-turn workers (batch jobs, CI tasks, scheduled scripts) with budget caps (turns / tokens / cost / wallclock) and a model-driven termination signal via the bundledtools.NewLifecycleTool. Pair with--ask=autoso instructions like "ask before doing X" get a clean refusal in headless contexts instead of blocking. - Durable sessions + audit log —
eventlog.Open(...)returns a SQLite/Postgres/MySQL-backedsession.Serviceplus aStreamwith monotonicseqnumbers,Since(seq)replay, andWatch(seq)live-tail. CLI flags--session-db/--session-db-pathenable persistence; the default path~/./sessions.dbis derived fromos.Executable()so adapters and forks each get their own directory. - Subagents —
agent.WithSubagents([]*Agent)registers each agent as a callable tool the parent's model can invoke by name (synchronous fan-out). For background subagents the parent's model decides to spawn at runtime, useagent.NewBackgroundAgentManager+ thespawn_agenttool family (in-process) oragent.NewSpawnRemoteAgentToolwith a consumer-suppliedRemoteAgentSpawner(out-of-process: gRPC / K8s Jobs / Cloud Run). Subagent reports flow back through a pre-turn drain so the parent sees them on its next turn. Subagent events stream into the same audit log underBranch="."(orBranch="bg."for background subagents) for branch-scoped replay. Seeexamples/with-subagent/andexamples/background-monitor/. - Optional Scion adapter — [
extras/scion-agent/](./extras/scion-agent/) packages core-agent for Scion's container runtime: lifecycle status emission,--inputtask delivery, and asciontool_statustool the model uses to declare sticky states. - Agent-card discovery — opt-in
/.well-known/agent-card.jsonon the attach listener describes the binary's name, description, skills, and required auth in the A2A AgentCard shape so Google Cloud Agent Registry (and any other consumer of the well-known path) can index it. Configured via.agents/agent-card.json+--agent-card-*flag overrides;.agents/skills/bundles auto-populate theskillsarray. The endpoint stays unauthenticated by spec convention; emitting a card does not imply the binary speaks the A2A JSON-RPC transport.
Releases
Tagged releases follow SemVer. See [CHANGELOG.md](./CHANGELOG.md) for the per-version history and the stability promise. Pre-1.0, breaking changes are possible at minor-version boundaries (v0.X); patches (v0.X.Y) are bug fixes only.
Current release: v1.8.0 — Remote operability. Five surfaces that together turn core-agent from a single-process CLI into a deployable, observable, controllable runtime: attach-mode (HTTP + Server-Sent Events live-tail + POST /inject + /wake for headless agents, with mTLS + bearer auth), peer registration (hub-and-spoke fleet discovery on top of attach), attach-config (.agents/config.json defaults + ${ENV_VAR} expansion so K8s ConfigMaps can replace 8+ CLI flags), read-only state endpoints (GET /sessions//tools|agents|status + permissions.Gate.Snapshot() so an operator surface can see what's gated without a re-run), and the core-agent-tui bubble-tea binary (separate cmd/core-agent-tui/; the default core-agent binary stays bubble-tea-free so distroless K8s images don't ship the TUI deps). Plus fetch_url — HTTP GET as a structured built-in with a url_scope allowlist mirroring path_scope, the one tool we picked up from Hermes Agent's catalog because it closes a real gap (bash curl shell-outs lose URL + status as structured eventlog metadata) and fits our structural-defaults posture (operator-declared url_scope.allow with HTTPS-only by default; per-host headers injection from env-var references so credentials never live on tool arguments). Two REPL fixes from UAT: external POST /inject now actually triggers a turn (the loop selects on stdin + wake instead of stdin only), and streamed model output gets an asst › chevron so the reply is visually distinct from the prompt. v1.7.0 was distroless-prep — three new built-ins (delete_file, stat, json_query via gojq) closing the gaps an upcoming K8s deployment using gcr.io/distroless/static would otherwise hit, plus a new Agent.RunWithContents driver for runtimes that own the conversation history. v1.6.0 added scheduled monitoring — tools.Scheduler + tools.SleepScheduler / ExitOnDeferScheduler + schedule_next_turn so the model emits "wake me at T+N" intent the autonomous driver honors between turns; validated against a real GKE cluster in dev/uat/scheduled-monitor. v1.5.0 added remote MCP servers (Google OAuth on .agents/mcp.json HTTP endpoints) plus two latent fixes. v1.4.0 retargeted Gemini tool-calling (parallelism mandate, tool-description rewrites, read_many_files, default-model flip to gemini-3.1-pro-preview-customtools). v1.3.0 added interrupt machinery (Agent.Inject, StartAutonomous → *AutonomousHandle, ESC-mid-turn + double-Ctrl+C-exits in the REPL). v1.2.0 added dynamic background subagents (spawn_agent) + a RemoteAgentSpawner seam. v1.1.0 added interactive permissions + Gemini grounding visibility. v1.0.1 patched two --provider=vertex regressions. v1.0.0 was the first stable release. Public API is under SemVer; breaking changes go through v1.X.0 minor bumps with a one-version deprecation period when feasible.
go get github.com/go-steer/core-agent@v1.8.0
Documentation
Full reference docs live at **** — getting started, every provider with env-var details, .agents/config.json schema, MCP setup, skills, permissions, and library API.
The site is built with Hugo using the Docsy theme; sources are in [docs/site/](./docs/site). To preview locally:
cd docs/site
npm install # one-time: postcss + autoprefixer (Docsy CSS pipeline)
hugo server # http://localhost:1313/core-agent/
Hugo Extended (≥ 0.146.0) is required — Docsy uses Hugo's SCSS pipeline.
Internal design docs live in [docs/](./docs) directly:
- [
DESIGN.md](./docs/DESIGN.md) — architectural rationale, the why behind the package layout, the Anthropic adapter, and the deliberate non-goals - [
acceptance-m1.md](./docs/acceptance-m1.md), [acceptance-m2.md](./docs/acceptance-m2.md) — per-milestone acceptance test plans
Install
As a CLI:
go install github.com/go-steer/core-agent/cmd/core-agent@latest
As a pre-built binary (linux/darwin × amd64/arm64; Sigstore signed):
# Pick the right archive from https://github.com/go-steer/core-agent/releases/latest
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. Verify signatures with cosign verify-blob --signature checksums.txt.sig --certificate checksums.txt.pem --certificate-identity-regexp '^https://github.com/go-steer/core-agent' --certificate-oidc-issuer https://token.actions.githubusercontent.com checksums.txt after downloading the checksum files.
As a library:
go get github.com/go-steer/core-agent
As a container image (v2.3.1+ — multi-arch amd64 + arm64; distroless static; Sigstore signed):
docker pull ghcr.io/go-steer/core-agent:latest # full build, in-process TUI included
docker pull ghcr.io/go-steer/core-agent-slim:latest # headless variant, ~5MB smaller (no embedded TUI)
docker pull ghcr.io/go-steer/core-agent-tui:latest # remote TUI client only
Floating tags: :latest (most recent semver), :X.Y.Z / :X.Y / :X (semver, no v prefix — matches Docker / Helm appVersion convention), :main (latest dev build), :main- (specific dev build). Verify signatures with cosign verify ghcr.io/go-steer/core-agent: --certificate-identity-regexp '^https://github.com/go-steer/core-agent' --certificate-oidc-issuer https://token.actions.githubusercontent.com.
Requires Go 1.26 or newer for source builds; container images carry their own toolchain.
Quick start — CLI
# Gemini API key (accepts either GEMINI_API_KEY or GOOGLE_API_KEY)
GEMINI_API_KEY=... core-agent -p "what's 2+2?"
# Vertex AI for Gemini (uses Application Default Credentials)
GOOGLE_GENAI_USE_VERTEXAI=true \
GOOGLE_CLOUD_PROJECT=my-gcp-project \
GOOGLE_CLOUD_LOCATION=us-central1 \
core-agent -p "what's 2+2?"
# Anthropic API key
ANTHROPIC_API_KEY=... core-agent --provider anthropic -p "what's 2+2?"
# Anthropic via Vertex AI (uses Application Default Credentials)
ANTHROPIC_VERTEX_PROJECT_ID=my-gcp-project CLOUD_ML_REGION=us-east5 \
core-agent --provider anthropic-vertex --model claude-opus-4-7 -p "what's 2+2?"
# Multi-turn REPL (no -p)
core-agent
> hello
…
> what number did I just say?
…
> /exit
CLI flags:
-p, --prompt string Single prompt; runs one turn and exits.
-c, --config string Config file path (default: discover .agents/config.json).
-m, --model string Override model name from config.
--provider string Override model.provider
(gemini|vertex|anthropic|anthropic-vertex|echo|scripted).
--no-builtin-tools Disable the built-in tool suite (read_file, write_file,
edit_file, list_dir, bash, todo).
--disable-tools Comma-separated list of built-in tools to disable
(e.g. bash,write_file). Composes by union with
cfg.tools.disable; ignored when --no-builtin-tools
is set.
--script string JSONL transcript for --provider=scripted.
--script-strict Scripted: assert each request matches the recorded one.
--record-to string Write a JSONL recording of all LLM turns to this path.
Works with any provider.
--color string ANSI color in streamed output: auto|always|never
(default: auto = on when stdout is a terminal,
off when piped). Tool calls render in cyan,
partial assistant text in green.
--ask string Register an ask_user tool the model can call:
off|stdin|auto (default: off). stdin reads from
os.Stdin; auto picks stdin when interactive,
else returns "(no user available)" so the model
adapts instead of blocking.
Quick start — library
package main
import (
"context"
"fmt"
"log"
"github.com/go-steer/core-agent/pkg/agent"
"github.com/go-steer/core-agent/pkg/config"
"github.com/go-steer/core-agent/pkg/models"
_ "github.com/go-steer/core-agent/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 _
…
## Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [go-steer](https://github.com/go-steer)
- **Source:** [go-steer/core-agent](https://github.com/go-steer/core-agent)
- **License:** Apache-2.0
- **Homepage:** https://go-steer.github.io/core-agent/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.