The predictable, observable agent harness.
Install · The Loop · Middleware · Observability · Configuration · Recipes
Agents run loops you can't see.
ra makes the loop explicit — and lets you control every step.
It runs tasks end-to-end like other agents, but unlike them, you can see, constrain, and reproduce everything it does. Not a framework. Not prompt chains. Just the loop, with control and visibility around it.
ra "Fix the failing tests and open a PR"curl -fsSL https://raw.githubusercontent.com/chinmaymk/ra/main/install.sh | bashWorks with Anthropic, OpenAI, Google, Ollama, Bedrock, and Azure — switch with --provider.
Stream the model response, execute tool calls in parallel, repeat. Every step fires a middleware hook.
User message → [beforeLoopBegin]
→ [beforeModelCall] → stream response → [afterModelResponse]
→ [beforeToolExecution] → execute tools → [afterToolExecution]
→ [afterLoopIteration] → repeat or [afterLoopComplete]
The loop runs until the model stops calling tools or a guardrail fires — no arbitrary iteration caps. Token budgets and duration limits trigger a clean shutdown:
agent:
maxTokenBudget: 500_000
maxDuration: 600_000Intercept any step in the loop. Full context at every step — read it, mutate it, stop it.
// middleware/audit.ts — log every tool call
export default async (ctx) => {
const { name, arguments: args } = ctx.toolCall
ctx.logger.info('tool', { name, args })
}// middleware/guard.ts — block destructive commands
export default async (ctx) => {
if (ctx.toolCall.name === 'Bash' && ctx.toolCall.arguments.includes('--force')) {
ctx.deny("Blocked: --force not allowed")
}
}Wire them to hooks in config:
agent:
middleware:
afterToolExecution:
- ./middleware/audit.ts
beforeToolExecution:
- ./middleware/guard.tsAvailable hooks: beforeLoopBegin, beforeModelCall, onStreamChunk, afterModelResponse, beforeToolExecution, afterToolExecution, afterLoopIteration, afterLoopComplete, onError.
Every model call, tool execution, and decision is captured automatically.
ra --inspector shows the full run: iterations, tokens, tools, traces, message history.
ra --inspector # web dashboard
ra --show-config # resolved config as JSON
ra --show-context # discovered context filesConfig lives in your repo. No hidden prompts, no default system prompt. One engineer defines behavior — everyone else runs the same agent.
# ra.config.yml
agent:
provider: anthropic
model: claude-sonnet-4-6
thinking: adaptive
maxTokenBudget: 500_000
skillDirs: [./skills]
permissions:
rules:
- tool: Bash
command:
allow: ["^git ", "^bun "]
deny: ["--force", "--hard", "--no-verify"]
- tool: Write
path:
deny: ["\\.env"]
middleware:
- ./middleware/token-budget.ts
- ./middleware/audit-log.ts
memory:
enabled: trueLayered overrides: defaults → config file → env vars → CLI flags. YAML, JSON, or TOML.
Complete agent configurations to fork and commit to your repo.
- Coding Agent — file editing, shell, adaptive thinking, context compaction
- Code Review Agent — GitHub MCP, style guide, diff scripts, token budget middleware
- Auto-Research Agent — autonomous ML research: run experiments, evaluate, iterate
- Multi-Agent Orchestrator — persistent specialist agents as independent processes
ra --config recipes/coding-agent/ra.config.yaml "Fix the failing test"Tools — filesystem, shell, web fetch, and a parallel sub-agent spawner. Each independently configurable or disabled.
Skills — reusable instruction bundles (code-review, architect, debugger, and more). Install from GitHub or npm.
MCP — expose skills as tools for Cursor, Claude Desktop, or other agents; connect to external MCP servers.
Memory — SQLite-backed persistent memory with full-text search, scoped per project.
Cron — run agent jobs on a schedule, each with isolated logs and traces.
GitHub Actions — uses: chinmaymk/ra@latest, no install step.
Full reference in the docs.
MIT
ra — The predictable, observable agent harness.
