Docs

Documentation

The platform, its surfaces (web, terminal, MCP, A2A), and the complete HTTP API. All endpoints return JSON; authentication is a session cookie or an etna_ Bearer key.

How Agent Etna works

What we mean by "AI agent": a system that pursues a goal on a user's behalf by deciding its own next steps. The LLM is the reasoning core; a harness — tools, memory, permissions, guardrails — is what lets it act, in a loop: plan, act through a tool, observe, adjust, repeat until done or a limit trips. The defining line is who chooses the path: in a workflow, a human wired the steps in code; in an agent, the model decides them at run time — which is why the same request can take a different route each run, and why agents are hard to test by hand.

Agent Etna is the harness around an AI agent you have already built. It profiles the agent, runs simulations that probe where it breaks, proposes ranked growths (changes) to fix what it finds, and ships them back to your repository under the same review process the rest of your code already uses. The product is a closed loop, run as a "cycle." Each step's output becomes the next step's input, and everything happens inside one chat-centric home view — there are no separate tabs to hunt through.

StepWhat happens
1. ConnectPoint Agent Etna at the agent's GitHub repository — pick it from the built-in repo list or type owner/repo. Bring your own LLM API key (every plan is BYOK); it's saved once, encrypted, and reused for every later connect.
2. ProfileAgent Etna reads the agent's own instructions, tools, and documented behaviour, and builds a capability map — what the agent is supposed to be able to do.
3. Run a simulationAgent Etna builds a simulation at the agent's capability frontier — the scenarios are always simulated; the agent's answers are always real (its live endpoint, its sandbox, or its own instructions run verbatim, and every result says which).
4. ScoreEach scenario gets a verdict, and the capability map updates — confirmed, still developing, or failing — with the scenario count behind each judgment, not just a single number.
5. Propose growthsFor each gap the simulation surfaced, Agent Etna proposes a specific change and ranks every proposal by impact, confidence, and effort.
6. Sandbox-verifyEvery accepted change proves itself first — built, run, and tested against the scenario that motivated it, plus the agent's established scenarios, before it ever reaches your repo.
7. ShipApprove, and it opens a real GitHub PR — branch protection, CODEOWNERS, required reviewers, and your existing CI all run on it like any other PR.
8. LearnEvery accepted change, every rejected one, every rollback sharpens what the next cycle proposes and how it ranks the backlog.

Navigation

The sidebar has: Home (the overview dashboard across every connected agent — click into one to reach its own chat and capability map), Releases (every version each agent has shipped — the ladder it climbs), your list of connected Agents, any Groups you've set up for multi-agent coordination, and Workspace / Keys / Profile under your account — Workspace also covers plan, seats, shared team keys, and inviting collaborators. A divider separates the two halves: above it is where the product happens, below it is what you configure.

Connecting an agent

Click Connect agent in the sidebar. You'll see a searchable list of your GitHub repositories — pick one (or type owner/repo manually), optionally set a branch, and add your own LLM API key. The key is required — every plan is BYOK, so simulations always bill to your own provider account, never the platform's — but it's asked for exactly once: it's stored encrypted and reused automatically on every later connect. Agent secrets (keys the agent itself needs, like Stripe or a database URL) aren't asked for up front — Etna asks right before it boots the agent's first sandbox, only if it actually needs one.

If the repo has no system prompt, we draft one for you to check. A simulation needs the agent's instructions to run in-process — without them it can only run against the live agent, so a sandbox that isn't up yet blocks you. Rather than let your first run fail and explain afterwards, Etna reads the repo at connect and, when it finds no prompt, drafts a baseline from what is actually there: the README and purpose docs, the routes and integrations in the code, the tool definitions. It arrives as an editable card that names its sources and marks its own guesses. Nothing is saved and nothing runs on it until you approve it — the draft is our work, the claim is yours. Replace it with the agent's real prompt whenever you prefer; from the terminal it's etna instructions <agent> --draft. The draft opens with what the agent is for, so approving it settles that question too — instructions and purpose are one thing here, and nothing asks you twice.

Running a simulation

Click Run a simulation — the chip sits right above the chat input on your agent's Home. A live progress card appears in the chat as the cycle moves through its steps; when it finishes you'll see the capability map and any proposed growths, with the highest-priority one called out in a Build this next banner.

Review and ship

Each recommendation reads as one plain paragraph — what to change and why, grounded in the scenario that exposed the gap. Click Ship on its card and it goes straight through: the change becomes a PR, runs the held-out gate and safety battery, and merges — the agent steps up its version ladder (v1.0 → v1.1). There is no separate holding pen; a recommendation lives in the chat until you ship or skip it. With several waiting, you don’t wait on each one: shipping queues the change and opens the next card immediately, and the queue merges them one after another in the background (one at a time, because two ships on the same agent would conflict on the same files). The line above the cards keeps up to date — and anything held back keeps its reason, and Releases shows every version each agent has shipped. Held-back changes stay as findings on the card, with the reason.

After a merge, we offer to watch. One line on the merge beat, one click: from then on we replay what your agent is known to handle against the live agent every night. A clean night is silent — you hear from us only when something that used to work stopped working, and then you get the evidence and the changes to ship. It is the same Scheduled check that lives in the agent's Autonomous panel and behind etna canary nightly; the offer just meets you where the value has already been proven.

What actually ran

The thread on the left is English, for deciding. The panel on the right is the machine’s own account of the same run, for believing — because the one thing a language model cannot fake is a microVM booting and a POST coming back 200 in 41 ms. Open it from the EXECUTION rail on the right edge, or from the what ran control on any scenario row, which opens it at that scenario.

It folds into four parts, each collapsible:

Every value in it comes from the run. A field the run did not measure prints as not measured — never 0 ms, never a zero that reads like a measurement. A check that did not run says which and why in the gate’s own words, and the footer says NOT GATED THIS RUN rather than wearing a pass it has not earned. “We did not test this” and “this held” are different answers, and the panel keeps them different.

Runs from before this shipped kept no execution record, so the panel says so for them too.

Slash commands

Typing / in the chat input opens a menu of shortcuts: /run starts a simulation (/run refund handling focuses it; /cycle is an alias), /record opens the agent's development record, /incident turns a real failure you paste into a scenario every future simulation re-checks, /consistency runs one scenario several times to see whether a pass is stable, /focus shows everything earlier simulations established around the agent, /spec edits its behavior expectations, /check runs the system check, /rollback reverts the last shipped change, and /help lists them all. The same actions are in the command palette (⌘K).

CLI

Everything above also works from your terminal — for you, your CI, or another agent. The etna CLI is a thin client on the same API this page documents, so your agents, simulations, recommendations and usage meter are shared with the dashboard in real time. They ARE the same data.

Connecting, step by step

1. Install it. The CLI isn't publicly distributed yet — it ships with platform access (we set you up during onboarding). From your copy of the code, npm link is what puts etna on your PATH:

cd agentetna
npm install
npm link

2. Mint a key. In the web app, open Settings → Keys → Etna API Keys and create one. It starts with etna_ and is shown once — copy it then.

3. Sign in. The key is verified against the server before it is stored, and it lands in ~/.config/etna/config.json with owner-only (0600) permissions:

etna login --key etna_…
# or, for CI and scripts:
export ETNA_API_KEY=etna_…

4. Check it worked. etna whoami names the account the key belongs to; etna agents lists what it can reach. An empty list means the key is valid but the account has no agents yet — connect one with etna connect owner/repo.

Signing out is etna logout, which removes the local key only. To cut off every machine using it at once, revoke the key on the web instead.

Commands

etna login --key etna_…      # verify + store the key (owner-only file)
etna agents                     # list your connected agents
etna connect                    # guided: lists your repos and asks; a monorepo asks which folder
etna connect owner/repo         # direct, when you know the repo
etna connect owner/repo --folder agents/livia    # one agent inside a monorepo
etna connect --url https://… --name clara     # an agent that isn't on GitHub
etna run                        # run a simulation — live verdicts in the terminal
etna stop                       # stop a hosted run — the scenario in flight finishes, verdicts are kept
etna check                      # every agent + every group: verdict per row, with the fix
etna verify                     # did this prompt edit break what the agent already did? exits non-zero if so
etna baseline                   # what this agent is KNOWN to do — every behaviour a simulation established
etna ship                       # list what a simulation proposed, confirm, then branch → PR → merge
etna ship --id <id>             # ship exactly one (--all ships them all as one PR; --skip <id> declines one)
etna versions                   # the shipped version ladder (v1.0 → v1.1 → …)
etna rollback                   # revert the last shipped change while it's still the branch head
etna ask "why did scenario 4 fail?"   # talk to Agent Etna — the exchange shows in the web thread too
etna secrets                    # this agent's secret NAMES (values are never shown)
etna secrets set OPENAI_API_KEY sk-…  # store one, encrypted; the sandbox rebuilds with it next run
etna scenarios                 # the latest run's scenarios; etna show 2 for one in full
etna focus                      # everything you've established for this agent; --drop <id> to remove one
etna incident "what went wrong" # a real failure becomes a permanent scenario — re-checked every simulation
etna incident                   # list incidents (open / passing); --drop <id> to remove one
etna canary nightly             # replay what it's known to do, live, every night — silent unless something broke
etna consistency                # same scenario, several samples — is a pass a pass, or a coin flip?
etna record                     # the development record — trajectory, versions, receipts, where it breaks
etna focus "Handoff pair"       # what you've established with the team
etna trace ./capture.har        # build the simulation from your agent's REAL traffic, not a guess
etna group                      # your saved groups — the same ones the sidebar shows
etna group create a b --name "Handoff pair"
etna group sim "Handoff pair" --focus "…"   # Etna designs the scenario; the focus joins the group's scenarios
etna group run "Handoff pair" --task "…"    # every member must answer live
etna group contract "Handoff pair"             # read the agreement first — ownership, handoff, escalation, authority
etna group backlog "Handoff pair"              # what this team should work on next — decide, repair, develop
etna group ship "Handoff pair"                 # ship the group change — every member's half, whole or not at all
etna instructions livia --draft     # no system prompt in the repo? draft one from it, approve, then run
etna history · etna status · etna settings · etna version

Recorded traffic outranks a guess. The environment a simulation builds is synthesised from the agent's profile — a reasonable guess about what its APIs return. etna trace ./capture.har replaces the guess with a recording of what your service actually returned, and every simulation from then on answers those endpoints for real. Credentials never reach disk: authorization headers and secret-looking body keys are stripped before anything is stored, and etna trace on its own shows only counts, hosts and endpoints — never bodies. A run built from a trace says so in its own result. etna trace --clear goes back to the synthesised environment.

A group run starts from the group's own chat. Open a group and Etna opens with what each member actually does and one question about what they're meant to achieve together — then a broad coordination check or a situation you name. It starts the run in the conversation; there is no separate form to fill in. What a group simulation observes is how the agents work together — who speaks to the user, who stays in the back office, what one hands the other, where they duplicate or contradict — never a second opinion on one member's solo behaviour, which the single-agent lane already does better.

Nobody is told whose turn it is. A group run puts each step to every member at once, and each one either takes it or passes — so what the run records is who claimed the work, where two agents both took the same step, and where nobody took it at all. Under a fixed rotation none of that is visible: the agent who handles a step is simply the agent whose turn it was. Passing is a real answer, and it is marked as one. If nobody will take the floor we name a speaker so the run still reaches an outcome, and those turns are labelled — they don't say who would have claimed.

The team works against a shared record, and the handoff is checked, not read. When a step produces something the others need — a reference number, an identifier, a figure, a date — the agent records it by name, and every member reads the same record. Nothing is inferred from the conversation: an agent that says the number out loud but never records it has not handed it over. That makes the commonest real coordination failure checkable without a model reading a transcript. Once a contract is shipped, every later run is measured against it — the fields it names either arrived, from the agent it names, or they didn't. Clauses a run never exercised are reported as untested rather than counted as held.

A group says what it is for, once. Each agent has its own instructions; what none of them contains is what the team does together, so a group gets one too — drafted from the members' own material and approved by you, in the same shape as an agent's. Without it the team's purpose is re-derived from member names on every run. And because three agents are usually written by three people to three conventions, the draft comes back with what their instructions do not settle: where two members contradict each other, where one field travels under two names, where a step is nobody's. Each is one click, each click writes one line, and “leave it — let the run show me” is always a valid answer. From the terminal: etna group instructions <group> --draft.

What a group simulation produces is a contract. Not a score — an agreement: who owns each step and who must not act on it, the named fields that must travel in a handoff (a reference number, a client id, a deadline), what each member does when the other is silent, and who may assign work to whom. Every clause is grounded in what the run actually showed; a run that found nothing to agree proposes nothing rather than a template. Read it with etna group contract or on the group's card, then ship it — each member gets only the clauses that bind them, written into its own instructions, whole or not at all.

Groups work from the terminal too. A group is a named set of two or more of your agents, and it is stored on the server — so one created with etna group create appears in the web sidebar, and one created there runs from your terminal. Group runs are strict live-only: every member has to answer a real ping or the run refuses to start and charges nothing. Naming two agents inline (etna group run alpha beta --task "…") still works for a one-off comparison you don't want to save.

Every command takes --json — and any non-interactive caller (a pipe, a script, another agent) gets stable JSON automatically, with no animation. Quotas, plan limits and safety gates are enforced server-side, identically to the web: the CLI holds no special powers beyond the key you mint.

The shipping gate — CI can refuse

With any threshold flag, etna run stops being a report and becomes a control. --min-pass-rate 0.9 fails the run when fewer than 90% of scored scenarios hold; --max-failures 0 fails it on any outright failure; --baseline last-report.json compares against a previous run, and a scenario that passed there and doesn't now fails the gate on its own — a rising average can hide exactly the behaviour a user relied on.

Exit codes carry the distinction CI needs: 0 the run completed and passed its gate, 1 the run itself broke (a malformed threshold refuses to run rather than silently passing), 2 the agent failed the gate. 1 versus 2 is "Etna fell over" versus "your agent regressed".

A scenario we couldn't actually test — your agent was unreachable, or the run was cut short on our side — never counts against you: our infrastructure will not fail your build. A run with too little real evidence reports inconclusive rather than passing by default. Any gated run writes the per-scenario results into its report, so today's report is tomorrow's --baseline.

Local mode — no account needed

etna run in your agent's repo runs a full cycle with your own LLM key — no account, nothing reaches the hosted platform. With no --url it boots the agent in the current directory itself (entry detection, a free port, stopped when the run ends), streams every exchange into the terminal as it happens, and then offers each proposed change as a real git diff with a single keypress: y applies it to your working tree, anything else skips. Nothing is committed — review with git diff, commit when happy, run again to re-simulate the patched agent. --url points it at an agent you started yourself; pipes and --json keep machine-readable JSON on stdout with no prompts. etna run picks the mode itself: --url, --repo or --local forces local, and a stored key (or ETNA_API_KEY) means hosted.

If it doesn’t work

Troubleshooting

After GitHub sign-in I land on a blank dashboard

Usually a stale cookie or cached HTML. Hard-refresh with Cmd+Shift+R (or Ctrl+Shift+R) and try again.

GitHub OAuth says redirect_uri_mismatch

The callback URL in your GitHub OAuth App must match <BASE_URL>/auth/github/callback exactly.

The profile step comes back thin

Agent Etna profiles your agent from whatever it can find — system prompt, README, tool definitions. If the profile looks sparse, add a short description of what the agent is supposed to do (an instructions, prompt, or README.md file all work) and run another simulation.

Engineering notes: testing multi-agent collaboration

The classic failure mode of agents that talk to each other isn't a crash — it's a conversation that never lands. Two agents defer to each other politely forever, re-ask the same clarifying question in a loop, or "hand off" a task back and forth without either one executing it. None of that throws an error, so none of it shows up in ordinary tests. It just burns tokens.

Group simulations in Agent Etna run every agent through a central broker rather than letting them call each other directly. That one architectural choice is what makes collaboration testable:

When a group cycle fails a collaboration scenario, the proposed growth targets the actual mechanism — a handoff prompt that never states completion criteria, a role instruction that makes both agents deferential — not a generic "improve coordination."

Engineering notes: testing tool use

An agent that calls its tools almost correctly is more dangerous than one that fails loudly. The canonical example: a payments tool times out on the response, the agent retries, and the refund goes out twice. The transcript looks fine. The bank balance doesn't.

Agent Etna tests tool use by running the agent against a synthesized mock-API environment that impersonates its real dependencies, with a deterministic mutation layer underneath:

The growths this produces are concrete: an idempotency check before the mutating call, a confirmation gate before destructive actions, a tool description rewritten so the agent stops guessing an ambiguous parameter. Each ships as a PR with the failing scenario attached as its proof.

Overview

Base URL: https://www.agentetna.com

Agent Etna exposes 133+ REST endpoints for testing, fixing, analyzing, and optimizing AI agents. The API supports three authentication methods:

Authentication

GitHub OAuth (Browser)

Navigate to /login to authenticate via GitHub. Session cookie is set automatically.

Bearer Token — GitHub personal access token

Authorization: Bearer <github-token>

Used by the GitHub Action. Your GitHub personal access token serves as the API key.

Bearer Token — Etna API key

Authorization: Bearer etna_...

Mint one under Keys → Etna API Keys — for your own agent (or any programmatic caller) to reach Agent Etna's HTTP/MCP surface on your behalf, scoped to specific permissions and optionally expiring. This is what the MCP server expects.

Agents

GET/api/agents

List all connected agents for the current user.

{
  "id": "my-agent",
  "name": "My Agent",
  "role": "customer support",
  "url": "https://my-agent.onrender.com",
  "github": { "repo": "user/repo", "branch": "main" }
}

POST/api/agents/connect auth

Connect a new agent.

ParameterTypeDescription
namestringAgent name (required)
sourcestringgithub, gitlab, bitbucket, replit, gitee, desktop
repostringowner/repo format
branchstringDefault: main
directUrlstringAgent URL (for desktop connections)

Fix Pipeline

POST/api/fix/start auth

Start a fix session using the graph-based orchestrator (reviewer-actor architecture, 2-pass review).

ParameterTypeDescription
errorsarrayErrors to fix [{userNote, ownerMsg, agentMsg}]
agentstringAgent ID
humanApprovalbooleanEnable pause-and-ask (default: false)
// Response
{ "id": "fix-1234567890" }

POST/api/fix/:id/apply auth

Deploy a ready fix to the agent's repository.

ParameterTypeDescription
branchstring"master" (direct) or "sandbox" (PR workflow)

POST/api/fix/:id/resume auth

Resume a paused fix (human-in-the-loop response).

ParameterTypeDescription
responsestring"approve", "request_changes", or "reject"
feedbackstringOptional feedback for the AI

GET/api/fix/:id/graph auth

Get the execution graph trace for a fix session.

GET/api/fix/stream auth

SSE stream for real-time fix progress. Events: fix (progress), ping (keepalive).

Tests

POST/api/tests/generate auth

Generate behavioral test cases from agent instructions.

POST/api/tests/baseline auth

Generate tests from agent instructions and run them.

POST/api/tests/run auth

Run all tests against the agent.

MCP Server

Agent Etna implements the Model Context Protocol — any MCP-compatible AI agent can discover and call Etna's tools.

It works in both directions. Etna is also an MCP client: declare your agent's MCP servers in a standard .mcp.json at the repo root and the System Check probes each remote one (real handshake + tool inventory, with the same URL safety rules as any agent endpoint), while etna run on your own machine verifies local stdio servers too and lists their tools in the run report. Local processes are never started on the hosted platform.

Connecting a client, step by step

1. Mint a key. Same key as the CLI — Settings → Keys → Etna API Keys in the web app. It starts with etna_ and is shown once.

2. Point your client at the endpoint. Etna speaks JSON-RPC 2.0 over HTTP at /mcp, authenticated with that key as a bearer token. In Claude Desktop, Cursor, or any client that reads a standard MCP config:

{
  "mcpServers": {
    "agent-etna": {
      "url": "https://www.agentetna.com/mcp",
      "headers": { "Authorization": "Bearer etna_…" }
    }
  }
}

3. Confirm the handshake. A client that has connected will list Etna’s tools — etna_cycle, etna_review, etna_next and the rest below. From a shell you can check the same thing without a client at all:

curl -s https://www.agentetna.com/mcp \
  -H "Authorization: Bearer etna_…" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

4. Drive the loop. etna_cycleetna_reviewetna_decide is the whole product, callable by another agent. etna_next gives it the single highest-leverage thing to do next.

The key carries exactly the permissions of the account that minted it, and revoking it on the web disconnects every client using it. If a client reports no tools, the key is missing or rejected — the tools/list call above will say which.

Endpoints

POST/mcp Bearer token

JSON-RPC 2.0 endpoint. Supports: initialize, tools/list, tools/call, ping.

// Example: list available tools
POST /mcp
Authorization: Bearer <token>
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list"
}

GET/mcp/tools public

List all MCP tools with schemas (convenience endpoint).

Available MCP Tools

The self-improvement loop — etna_cycleetna_reviewetna_decide → loop (with etna_next/etna_fix for targeted fixes, skipping dismissed items via etna_next's skip param) — is the fastest way for another agent to drive Etna end to end. GET /mcp/tools is the live, authoritative list (schemas included); this table is a summary.

ToolDescription
etna_cycleRun a full developmental cycle: profile, capability-frontier scenarios, scoring, growth proposals — "how is my agent doing right now?"
etna_reviewThe recommendations a simulation proposed, awaiting a decision — the same ones a cycle-result card carries on the web
etna_versionsThe shipped version ladder (v1.0 → v1.1 → …) — the twin of the web Releases page and etna versions
etna_decideApprove or skip one recommendation; the decision feeds the same learning loop as the web
etna_nextThe single highest-leverage next improvement from the ranked growth backlog, with file/line/why/suggested-action
etna_fixGenerate and deploy fixes for agent bugs (sniper-located patches, judge-reviewed)
etna_testGenerate behavioral tests from the agent's instructions and code
etna_statusCheck connection health, latency, and basic info for connected agents
etna_profileArchetype, capability list, environment primitives, and a one-paragraph purpose narrative
etna_tracesRecent production traces — input, output, verdict, latency — for diagnosing a regression
etna_memoryRead or update the calling user's preference profile Etna already holds, encrypted at rest
etna_sandbox_listList active sandbox branches — fix runs staged but not yet promoted to the agent's main branch
etna_agent_cardThe agent's public A2A AgentCard — the discovery document peers use to find its skills and auth scheme
etna_analyzeArchitecture read of the agent: source files, API routes, external services, call graph, circular dependencies
etna_watchRead or set the nightly Scheduled check — replays what the agent is known to handle against the live agent, silent unless something broke
etna_recordThe development record: version axis, capability trajectory, where it breaks, incidents, and what was caught while nobody was looking
etna_incidentTurn a real production failure into a permanent scenario every future simulation re-checks; list or drop what is already imported
etna_instructionsWhether the agent has a system prompt, and a baseline draft from its own repo for review — nothing is saved until you pass back the words you approve
etna_group_instructionsWhat a GROUP is for, together — the group twin. Reads the team’s charter, or drafts one from the members’ own material along with what their instructions do not settle (a contradiction, a field travelling under two names, a step nobody claims). Nothing is saved until you pass back the words you approve

GitHub Action

Add Agent Etna to your CI pipeline:

- uses: AgentEtna/etna-core@master
  with:
    agent-url: https://my-agent.onrender.com
    etna-api-key: ${{ secrets.ETNA_API_KEY }}
    auto-fix: true
    test-count: 10
    security-scan: true

Outputs

OutputDescription
tests-passedNumber of tests that passed
tests-failedNumber of tests that failed
fixes-generatedNumber of fix patches generated
pr-urlURL of the created PR
security-issuesNumber of security vulnerabilities found

System Health

GET/healthz public

Health check. Returns {"ok":true,"uptime":1234}.

Agent Etna API — tracks the platform build (currently v1.0.0)