Project guide

Project Guide | Agent Runtime Go

Free Go agent-runtime reliability checklist for retries, tools, and provider adapters. This guide organizes the repository's original implementation notes for Go engineers building deterministic agent runtimes.

Reviewed 2026-07-28. This page is derived from checked-in repository evidence and links back to its source.

Agent Reliability Audit Surface

A minimal, production-grade LLM agent orchestration runtime in Go. Deterministic tool-calling, retry with backoff, pluggable LLM providers, streaming-ready. Companion to stage-pilot (TypeScript) in the same design family.

Architecture pack: `docs/architecture-pack.md`

---

Three-Minute Proof

  1. Inspect the runner, tool schema, retry, and provider boundaries.
  2. Run make verify to execute Go tests and repository validation.
  3. Check timeout, retry, and deterministic-tool behavior before adding providers.
  4. Read it as the compact Go companion to stage-pilot, not a broad framework.

System Overview

LensCurrent answer
UsersBackend and platform teams that want agent execution inside Go services without a large framework.
Technical pathValidate the demo, README, architecture notes, and quality gate before deeper workflow review.
System scopeGo-native runner, deterministic tool replay, retry/backoff, provider interface, and compact auditable core.
Operating boundaryTool execution is bounded by schemas, timeouts, circuit breakers, and explicit provider adapters.
Evaluation pathmake verify, `docs/architecture-pack.md`, and the StagePilot design-family link.

Evaluation Path

---

Architecture Notes

Why

The JavaScript/TypeScript ecosystem has stage-pilot, LangChain.js, AI SDK. The Python ecosystem has stage-pilot, LangGraph, CrewAI. The Go ecosystem, as of April 2026, has fragmented options and few patterns focused on reliability and determinism at the tool-call boundary.

This repository fills that gap. It's:

What it does

Given a user prompt and a set of tools:

  1. Calls the LLM with the prompt + tool schemas.
  2. Parses the LLM response into structured tool calls (with JSON-in-markdown tolerance).
  3. Validates arguments against each tool's schema.
  4. Executes tools with configurable timeout + circuit breaker.
  5. Feeds results back to the LLM.
  6. Loops until the LLM emits a final answer (or hits max-step limit).

Verify the runtime

git clone https://github.com/KIM3310/agent-runtime-go.git
cd agent-runtime-go
make verify


## If Go is installed outside PATH:
make GO=/path/to/go verify
package main

import (
    "context"
    "fmt"
    "os"

    "github.com/KIM3310/agent-runtime-go/runtime"
    "github.com/KIM3310/agent-runtime-go/providers/anthropic"
)

func main() {
    provider := anthropic.New(os.Getenv("ANTHROPIC_API_KEY"))

    tools := []runtime.Tool{
        {
            Name:        "get_weather",
            Description: "Get current weather for a city",
            InputSchema: map[string]any{
                "type": "object",
                "properties": map[string]any{
                    "city": map[string]any{"type": "string"},
                },
                "required": []string{"city"},
            },
            Handler: func(ctx context.Context, args map[string]any) (any, error) {
                city, _ := args["city"].(string)
                return map[string]string{"city": city, "temp": "18C", "condition": "clear"}, nil
            },
        },
    }

    runner := runtime.NewRunner(provider, runtime.WithTools(tools))
    result, err := runner.Run(context.Background(), "What's the weather in Seoul?")
    if err != nil {
        panic(err)
    }
    fmt.Println(result.FinalAnswer)
}

Architecture

                     ┌──────────────┐
User prompt ────────▶│    Runner    │◀── Config (max_steps, timeout, ...)
                     └──────┬───────┘
                            │
         ┌──────────────────┼──────────────────┐
         ▼                  ▼                  ▼
   ┌──────────┐     ┌──────────────┐   ┌──────────────┐
   │ Provider │     │ Tool Parser  │   │ Tool Dispatcher │
   └─────┬────┘     └──────┬───────┘   └───────┬──────┘
         │                 │                   │
         ▼                 ▼                   ▼
   Anthropic API   Parses LLM output   Validates args,
   OpenAI API      for tool_use        executes tool,
   Bedrock         blocks              handles timeout

Why Go?

Why minimal?

Smaller surface area = smaller attack surface = smaller maintenance burden. Production deployments can audit 1200 LOC; they can't audit 120,000 LOC.

Why deterministic replay?

Production incidents need reproducible debugging. Given the same prompt + tool fixtures + LLM response, the runner produces byte-identical tool calls. No hidden non-determinism from map iteration order, goroutine scheduling, or timestamp injection.

Provider interface

type Provider interface {
    Generate(ctx context.Context, req Request) (Response, error)
    // GenerateStream optional; returns ErrNotSupported if provider can't stream
    GenerateStream(ctx context.Context, req Request) (<-chan Event, error)
}

Implementations:

Tool registration

Two patterns:

1. Plain struct (fast to write):

tool := runtime.Tool{
    Name:        "query_sql",
    Description: "Execute a read-only SQL query",
    InputSchema: map[string]any{...},
    Handler: func(ctx context.Context, args map[string]any) (any, error) {
        sql, _ := args["sql"].(string)
        return executeQuery(sql)
    },
}

2. Typed handler (compile-time safety):

type QueryArgs struct {
    SQL     string `json:"sql" jsonschema:"required"`
    Timeout int    `json:"timeout_seconds"`
}

type QueryResult struct {
    Rows  []map[string]any `json:"rows"`
    Count int              `json:"count"`
}

tool := runtime.TypedTool[QueryArgs, QueryResult]{
    Name:        "query_sql",
    Description: "Execute a read-only SQL query",
    Handler: func(ctx context.Context, args QueryArgs) (QueryResult, error) {
        return executeQuery(args.SQL, args.Timeout)
    },
}

Typed tools generate the JSON Schema at compile time via go generate.

Comparison to alternatives

Featureagent-runtime-goLangChain Golangchaingoollama-go
Tool-call validationBuilt-inPartialPartialNo
Deterministic replayYesNoNoNo
Multi-providerYesYesYesOllama only
Bench on agent-orchestration-benchmarkYes (90%+)YesPartialNo
LOC~1200~15K~10K~3K
OpenTelemetryFirst-classPartialPartialNo

Running the benchmark


## Requires ANTHROPIC_API_KEY, OPENAI_API_KEY, or OPENROUTER_API_KEY
go test -v -run TestAgentOrchestrationBenchmark ./tests/


## Against the formal benchmark suite
go run ./cmd/bench-runner \
    --fixture-set ../agent-orchestration-benchmark/fixtures/benchmark_prompts.jsonl \
    --output bench-results.json

Observability

All operations emit OpenTelemetry spans:

Attributes include: runtime.step_count, runtime.tool_call_attempt_count, llm.input_tokens, llm.output_tokens, tool.success_or_error.

Metrics emitted to Prometheus via metrics/ package:

Related projects

RepoRelationship
stage-pilotTypeScript sibling. Same design philosophy; different language.
agent-orchestration-benchmarkBenchmark suite; agent-runtime-go is scored alongside LangGraph, CrewAI, AutoGen.
claude-agent-cookbookPython cookbook; Go port patterns to be added in examples/
claude-production-patternsProduction patterns referenced in runtime/circuit_breaker.go

Cloud + AI Architecture

Enterprise Productization

System Architecture

Service Architecture

Search And Service Surface