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

Routex

mcp-ad3bay0c-routex · by Ad3bay0c

Lightweight AI agent runtime for Go. Define multi-agent crews in YAML, run them with goroutines and channels, and let the runtime handle scheduling, parallelism, retries, and observability — without leaving the Go ecosystem.

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

Install

$ agentstack add mcp-ad3bay0c-routex

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

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-ad3bay0c-routex)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo 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 Routex? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

  ██████╗  ██████╗ ██╗   ██╗████████╗███████╗██╗  ██╗
  ██╔══██╗██╔═══██╗██║   ██║╚══██╔══╝██╔════╝╚██╗██╔╝
  ██████╔╝██║   ██║██║   ██║   ██║   █████╗   ╚███╔╝
  ██╔══██╗██║   ██║██║   ██║   ██║   ██╔══╝   ██╔██╗
  ██║  ██║╚██████╔╝╚██████╔╝   ██║   ███████╗██╔╝ ██╗
  ╚═╝  ╚═╝ ╚═════╝  ╚═════╝    ╚═╝   ╚══════╝╚═╝  ╚═╝

  lightweight AI agent runtime for Go

[](https://pkg.go.dev/github.com/Ad3bay0c/routex) [](https://goreportcard.com/report/github.com/Ad3bay0c/routex) [](https://codecov.io/github/Ad3bay0c/routex) [](https://github.com/Ad3bay0c/routex/stargazers) [](https://opensource.org/licenses/MIT) [](https://github.com/avelino/awesome-go)

A lightweight AI agent runtime for Go.

Routex lets you build, run, and supervise multi-agent AI crews using the primitives Go developers already know — goroutines, channels, and interfaces. Define your crew in a YAML file or pure Go code, wire in any LLM provider and tools, and let the runtime handle scheduling, parallelism, retries, memory, and observability.

go install github.com/Ad3bay0c/routex/cmd/routex@latest
routex init my-crew && cd my-crew
cp .env.example .env   # add your API key
routex run agents.yaml

To depend on Routex from your own Go program (not the CLI):

go get github.com/Ad3bay0c/routex@latest

See [Using it as a library](#using-it-as-a-library) for imports and examples.


Why Routex?

The AI agent ecosystem is almost entirely Python. Frameworks like LangGraph and CrewAI are powerful but they carry a Python runtime, slow cold starts, and async complexity that does not belong in production Go services.

Routex is built for Go developers who want agentic capabilities without leaving the Go ecosystem.

| | LangGraph | CrewAI | Routex | | ------------------- | ---------- | ---------- | ------------------------- | | Language | Python | Python | Go | | Concurrency model | asyncio | asyncio | goroutines + channels | | Agent supervision | none | none | Erlang-style OTP tree | | Binary size | heavy | heavy | ~10 MB single binary | | Cold start | ~2–5 s | ~2–5 s | ~50 ms | | Multi-LLM per agent | no | no | yes | | OpenTelemetry | partial | partial | first-class | | Deploy target | Python env | Python env | any OS, Docker, K8s |


Table of Contents

  • [Concepts](#concepts)
  • [Quickstart](#quickstart)
  • [Using the CLI](#using-the-cli)
  • [Using it as a library](#using-it-as-a-library)
  • [YAML reference](#yaml-reference)
  • [Built-in tools](#built-in-tools)
  • [LLM providers](#llm-providers)
  • [Multi-LLM crews](#multi-llm-crews)
  • [Memory backends](#memory-backends)
  • [MCP tool servers](#mcp-tool-servers)
  • [Restart policies](#restart-policies)
  • [Observability](#observability)
  • [Writing a custom tool](#writing-a-custom-tool)
  • [CLI reference](#cli-reference)
  • [GitHub Actions](#github-actions)
  • [Environment variables](#environment-variables)
  • [Repo layout](#repo-layout)
  • [Roadmap](#roadmap)

Concepts

Routex borrows ideas from operating systems and applies them to AI agents:

Agent — a long-lived goroutine with a brain (LLM), a memory scope, and a set of tools. Agents wait on an Inbox channel, process one task at a time, and send results back through typed channels. They never share state.

Crew — a collection of agents that work together on a task. Agents declare depends_on relationships; the scheduler turns these into a DAG and runs independent agents in parallel.

Scheduler — performs topological sort (Kahn's algorithm) on the dependency graph. Agents with no dependencies run immediately in parallel. Each subsequent wave starts only when the previous wave completes. Detects cycles at startup, before any agent runs.

Supervisor — watches agents via a dedicated notify channel. When an agent fails, the scheduler asks the supervisor what to do. The supervisor checks the agent's restart budget and returns a decision: retry or give up. This design means the scheduler never advances a wave past a failed agent — it blocks until the supervisor resolves the failure.

Tool — anything an agent can call: web search, file read/write, HTTP request, translation, image generation. Implement one interface, register once, available to any agent.

Memory — each agent has a namespaced key-value and message history store. In-memory by default; Redis for persistence across runs.

Runtime — the orchestrator. Builds the agent graph, wires in the LLM adapters, starts the supervisor, hands tasks to the scheduler, and collects results.


Quickstart

Using the CLI

The fastest path — no Go code required.

# Install
go install github.com/Ad3bay0c/routex/cmd/routex@latest

# Scaffold a new project
routex init my-research-crew
cd my-research-crew

# Set up environment
cp .env.example .env
# Edit .env — add your ANTHROPIC_API_KEY

# Edit the generated agents.yaml file

# Validate the config
routex validate agents.yaml

# See the execution plan before running
routex run agents.yaml --dry-run

# Run it
routex run agents.yaml

Override the task inline without editing YAML:

routex run agents.yaml --task "Compare the latest releases of Go and Rust"

Use a different env file (e.g. production secrets injected by your platform):

routex run agents.yaml --env-file .env.staging --output ./reports/result.md

Using it as a library

Import Routex into any Go application. Task input can come from an HTTP request, message queue, database — anywhere.

Add the module to your project (this is the library dependency — unlike go install, which only builds the routex CLI):

go get github.com/Ad3bay0c/routex@latest

Then import the root package and any subpackages you need (see below). If you add imports first, go mod tidy will record the module as well.

| Goal | Command | | ----------------------------- | ---------------------------------------------------------- | | Use Routex from your Go code | go get github.com/Ad3bay0c/routex@version | | Install the routex CLI only | go install github.com/Ad3bay0c/routex/cmd/routex@version |

Tool imports — opt in to what you need

Routex's built-in tools are in separate sub-packages so you only compile what you use. Import tools/all for everything, or pick individual packages for a leaner binary:

// All 11 built-in tools (convenience — larger binary)
import _ "github.com/Ad3bay0c/routex/tools/all"

// Or import only what you need (smaller binary, fewer dependencies)
import (
    _ "github.com/Ad3bay0c/routex/tools/file"   // read_file, write_file
    _ "github.com/Ad3bay0c/routex/tools/search" // web_search, brave_search, wikipedia
    _ "github.com/Ad3bay0c/routex/tools/web"    // http_request, read_url, scrape
    // omit tools/ai   → no OpenAI/Anthropic SDK dependency
    // omit tools/comms → no SendGrid/Resend dependency
)

Option 1 — YAML-driven (recommended for most use cases):

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/Ad3bay0c/routex"
    _ "github.com/Ad3bay0c/routex/tools/all" // register all built-in tools
)

func main() {
    ctx := context.Background()

    // LoadConfig reads agents.yaml, loads .env via env_file:,
    // resolves all env: references, and validates the agent graph.
    rt, err := routex.LoadConfig("agents.yaml")
    if err != nil {
        log.Fatal(err)
    }

    result, err := rt.StartAndRun(ctx)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Done in %s — %d tokens\n", result.Duration, result.TokensUsed)
    rt.Stop()
}

Option 2 — override task at runtime:

rt, _ := routex.LoadConfig("agents.yaml")

// Task comes from an HTTP request, not from YAML
rt.SetTask(routex.Task{
    Input: r.FormValue("topic"),
})

// Or pass directly to LoadConfig
rt, _ := routex.LoadConfig("agents.yaml",
    routex.WithTaskInput(r.FormValue("topic")),
    routex.WithEnvFile(".env.prod"),
)

result, _ := rt.StartAndRun(ctx)

Option 3 — fully programmatic (no YAML):

import (
    "github.com/Ad3bay0c/routex"
    "github.com/Ad3bay0c/routex/agents"
    "github.com/Ad3bay0c/routex/tools/search"
    "github.com/Ad3bay0c/routex/tools/file"
)

rt, _ := routex.NewRuntime(routex.Config{
    Name: "my-crew",
    LLM: routex.LLMConfig{
        Provider: "anthropic",
        Model:    "claude-sonnet-4-6",
        APIKey:   os.Getenv("ANTHROPIC_API_KEY"),
    },
})

rt.RegisterTool(search.WebSearch())
rt.RegisterTool(file.WriteFileIn("./outputs"))

rt.AddAgent(agents.AgentConfig{
    ID:    "researcher",
    Role:  agents.Researcher,
    Goal:  "Find recent news about Go 1.24",
    Tools: []string{"web_search"},
})

rt.AddAgent(agents.AgentConfig{
    ID:        "writer",
    Role:      agents.Writer,
    Goal:      "Write a summary report and save it",
    Tools:     []string{"write_file"},
    DependsOn: []string{"researcher"},
})

result, _ := rt.StartAndRun(ctx)

YAML reference

runtime:
  name: "my-crew" # identifies this crew in logs and traces
  llm_provider: "anthropic" # anthropic | openai | ollama | gemini
  model: "claude-sonnet-4-6" # model name for the chosen provider
  api_key: "env:ANTHROPIC_API_KEY" # env:VAR reads from environment
  log_level: "info" # debug | info | warn | error
  env_file: "." # DEVELOPMENT ONLY — load .env next to this file
  # base_url:   "env:CUSTOM_ENDPOINT"  # override LLM API endpoint

task:
  input: "Research the latest Go releases"
  output_file: "env:OUTPUT_FILE" # env: works in any string field
  max_duration: "5m" # Go duration string — 30s, 5m, 1h

tools:
  # Built-in tools — declare here, auto-registered by the runtime
  - name: "web_search" # DuckDuckGo, free, no key

  - name: "brave_search" # Higher quality, 2,000 free/month
    api_key: "env:BRAVE_API_KEY"
    max_results: 5

  - name: "wikipedia" # Free, no key needed
    extra:
      language: "en"

  - name: "http_request" # Call any REST API
    api_key: "env:MY_API_KEY" # sent as X-Api-Key header
    extra:
      bearer_token: "env:MY_TOKEN" # sent as Authorization: Bearer
      query_api_key: "env:OWM_KEY" # sent as query param (e.g. OpenWeatherMap)
      query_api_key_name: "appid" # the param name (?appid=KEY)
      param_units: "metric" # default query param on every request
      header_Accept: "application/json"

  - name: "write_file"
    base_dir: "./outputs" # agents can only write inside this dir

  - name: "read_file"
    base_dir: "./data"

  - name: "read_url" # Fetch and strip HTML from any URL

  - name: "scrape" # JS-rendered pages via ScrapingBee
    api_key: "env:SCRAPINGBEE_API_KEY"

  - name: "summarise" # LLM-powered text compression
    api_key: "env:ANTHROPIC_API_KEY"

  - name: "translate" # DeepL API, 500k chars/month free
    api_key: "env:DEEPL_API_KEY"

  - name: "generate_image" # DALL-E 3 via OpenAI
    api_key: "env:OPENAI_API_KEY"
    base_dir: "./outputs/images"

  - name: "send_email" # SendGrid or Resend
    api_key: "env:SENDGRID_API_KEY"
    extra:
      provider: "sendgrid" # sendgrid | resend
      from_email: "agent@example.com"
      from_name: "Routex Agent"

  - name: "mcp" # MCP server call
    extra:
      server_url: "http://localhost:3000"
      server_name: "github"

  - name: "mcp"
    extra:
      server_url: "http://localhost:3001"
      server_name: "postgres"

agents:
  - id: "researcher" # unique within this crew
    role: "researcher" # planner | researcher | writer | critic | executor
    goal: "Find and summarise recent Go releases"
    tools: ["web_search", "read_url"]
    restart: "one_for_one" # one_for_one | one_for_all | rest_for_one
    max_retries: 2
    timeout: "90s"
    # depends_on: []                   # list of agent IDs that must complete first
    # max_duplicate_tool_calls: 2      # redirect LLM after N identical tool calls (default: 2)
    # max_total_tool_calls: 20         # absolute tool call budget per attempt (default: 20)

    # Per-agent LLM override — uses a different model from the runtime default
    # llm:
    #   provider: "openai"
    #   model:    "gpt-4o"
    #   api_key:  "env:OPENAI_API_KEY"

  - id: "writer"
    role: "writer"
    goal: "Write a markdown report. Save it as report.md"
    tools: ["write_file"]
    depends_on: ["researcher"] # starts only after researcher finishes
    restart: "one_for_one"
    max_retries: 2
    timeout: "120s"

memory:
  backend: "inmem" # inmem | redis
  ttl: "1h"
  # redis_url: "env:REDIS_URL"         # required when backend is "redis"

observability:
  tracing: false
  metrics: false
  # jaeger_endpoint: "env:OTEL_EXPORTER_OTLP_ENDPOINT"  # e.g. http://localhost:4318
  # metrics_addr:    ":9090"           # curl localhost:9090/metrics

The env: prefix

Any string value in the YAML can read from the environment:

api_key: "env:ANTHROPIC_API_KEY" # reads os.Getenv("ANTHROPIC_API_KEY")
output_file: "env:OUTPUT_PATH" # works in any string field
model: "env:LLM_MODEL" # even model names

This means your agents.yaml file can be committed to git with zero secrets in it.


Built-in tools

All tools are registered automatically when listed in the tools: section of agents.yaml. No RegisterTool() call needed for built-ins.

Search & Data

| Tool | Key needed | Free tier | Description | | -------------- | --------------------- | ------------------- | ------------------------------------------- | | web_search | none | unlimited | DuckDuckGo Instant Answers | | brave_search | BRAVE_API_KEY | 2,000/month | Structured web results with publication age | | wikipedia | none | unlimited | Wikipedia article summaries, 300+ languages | | scrape | SCRAPINGBEE_API_KEY | 1,000 credits/month | JS-rendered page content |

Web & HTTP

| Tool | Key needed | Description | | -------------- | ------------ | ------------------------------------------------- | | read_url | none | Fetch and strip HTML from any URL | | http_request | configurable | Call any REST API — GET, POST, PUT, PATCH, DELETE |

http_request supports four authentication patterns:

# 1. Query string key (OpenWeatherMap, Google Maps)
extra:
  query_api_key:      "env:OWM_KEY"
  query_api_key_name: "appid"         # → ?appid=KEY on every request

# 2. Bearer token (GitHub, most REST APIs)
extra:
  bearer_token: "env:GITHUB_TOKEN"   # → Authorization: Bearer TOKEN

# 3. API key header
api_key: "env:MY_KEY"                # → X-Api-Key: KEY

# 4. Custom header
extra:
  header_X-Custom-Header: "value"    # → X-Custom-Header: value
  header_API-KEY: "value"    # → API-KEY: value

Default query params (sent on every request):

extra:
  param_units: "metric" # → ?units=metric on every request
  param_lang: "en"

File

| Tool | Config | Description | | ------------ | ---------- | ------------------------------------- | | write_file | base_dir | Write files — sandboxed to base_dir | | read_file | base_dir | Read files — sandboxed to base_dir |

Path traversal (../) is blocked in both tools. Agents can only read or write inside the configured base_dir.

AI & Generation

| Tool | Key needed | Description | | ---------------- | ------------------- | -----------------------------------------

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

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.