AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified Apache-2.0 Self-run

Core Agent

mcp-go-steer-core-agent · by go-steer

Reusable Go base agent on the Google ADK — multi-provider (Gemini, Vertex, Claude on Anthropic + Vertex), MCP-native, with AGENTS.md, skills, and permissions wired up.

No reviews yet
0 installs
38 views
0.0% view→install

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.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-go-steer-core-agent)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

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 →
Are you the author of Core Agent? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

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.Runner with 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_KEY or GEMINI_API_KEY (either is accepted; GEMINI_API_KEY is 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 ADK model.LLM adapter (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=echo returns the user prompt verbatim; --provider=scripted --script=transcript.jsonl replays a recorded session. Pair with --record-to=path.jsonl against any provider to capture a transcript for later replay.
  • AGENTS.md instruction loading — system prompt prefix is assembled from ~/.core-agent/AGENTS.md and the project's AGENTS.md (with CLAUDE.md / GEMINI.md fallbacks), 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.md bundle into .agents/skills// and the agent can invoke it on demand via ADK's skilltoolset.
  • Built-in tool suiteread_file, write_file, edit_file, list_dir, glob, grep, bash, todo. Wired up by default in the bundled CLI; opt-out via --no-builtin-tools for the whole suite, or --disable-tools=bash,write_file (or tools.disable in 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, ask mode prompts the user interactively (y/s/t/a/N) when stdin is a TTY; --yolo bypasses the gate entirely for headless use.
  • Server-side built-in observability — Gemini's GoogleSearch activity surfaces in the chat-style stdout (↪ google_search: query: ..., ↪ google_search: — ) and as queryable gemini/google_search-authored rows in the eventlog when --session-db is 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 CLIcore-agent -p "prompt" for one-shot use; bare core-agent drops into a stdin REPL with conversation history preserved across turns.
  • Autonomous-run driveragent.RunAutonomous for 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 bundled tools.NewLifecycleTool. Pair with --ask=auto so instructions like "ask before doing X" get a clean refusal in headless contexts instead of blocking.
  • Durable sessions + audit logeventlog.Open(...) returns a SQLite/Postgres/MySQL-backed session.Service plus a Stream with monotonic seq numbers, Since(seq) replay, and Watch(seq) live-tail. CLI flags --session-db / --session-db-path enable persistence; the default path ~/./sessions.db is derived from os.Executable() so adapters and forks each get their own directory.
  • Subagentsagent.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, use agent.NewBackgroundAgentManager + the spawn_agent tool family (in-process) or agent.NewSpawnRemoteAgentTool with a consumer-supplied RemoteAgentSpawner (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 under Branch="." (or Branch="bg." for background subagents) for branch-scoped replay. See examples/with-subagent/ and examples/background-monitor/.
  • Optional Scion adapter — [extras/scion-agent/](./extras/scion-agent/) packages core-agent for Scion's container runtime: lifecycle status emission, --input task delivery, and a sciontool_status tool the model uses to declare sticky states.
  • Agent-card discovery — opt-in /.well-known/agent-card.json on 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 the skills array. 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.

Versions

  • v0.1.0 Imported from the upstream source.