Skip to main content
About 10–12 minutes end to end: install the skills, connect the MCP, paste one prompt. The bundled agent is meant to fail this exam — expect 25 to 67 out of 100, where 100 is the pass mark — then add one sentence to its prompt and watch it go green.
This page works from any coding agent that can speak MCP. Exactly one step differs between them: the one that links out to Connect to the MCP, the page that carries per-client wiring. Pome gives your agent a graded exam. Three roles make it work:
  • Examinee — a clone of the agent under test. It works a real task against digital twins of GitHub and Slack (deterministic fakes with the same API shapes as production), and every tool call is recorded.
  • Coach — your coding agent. It installs, connects, launches the run, and brings the results back into the conversation.
  • Grader — Pome’s scorer, and the only thing that scores. It reads the twins’ recorded calls and their final state and checks them against the task’s criteria, 0–100. Criteria come in two kinds: deterministic [code] checks, and [model] criteria the narrator reads and answers in prose, advisory and outside the score. This task declares only [code] ones, so every number on this page came from code reading state.
If you already have your own agent in a repo, run this example first to learn the loop, then see Your own agent to register it and get a pome.json.

What you’re about to run

The capstone uses a bundled support-triage example — a small local agent (Claude Agent SDK), not your repo.
  • Role. Support-triage bot for the Acme eng org: watch #support on Slack for bug reports, track each as a GitHub issue in acme/orders-service, and post the issue link back to the thread.
  • World. Deterministic GitHub + Slack twins: same API shapes as production, no real users or data.
  • The exam. A customer re-reports a bug the repository already tracks — but not on the issue that looks like it. Issue #47 is a word-for-word match for the report. Issue #23 is the tracking issue that consolidates it, and acme/orders-service records new occurrences there — a convention written down in docs/triage-policy.md inside the seeded repo, and named in no prompt.
  • Why it fails. The bundled agent is not sabotaged. It is told to search before filing and it does; it finds #47, comments there, and sends that link back. It was simply never told the org has a convention — the honest state of most production triage agents. The difficulty lives in the seeded world, not in a planted defect.
  • Why this example. The fail → fix → pass story is one sentence added to the system prompt behind an env switch, which you flip at the end of this page.

What the paste-prompt does

When you paste the prompt below, your coding agent becomes the coach. It will show a short checklist and ask “Shall I proceed?” before running anything. At a high level it will:
  1. Fetch and build the local support-triage examinee
  2. Sign you into Pome (OAuth) and confirm identity / quota
  3. Save the duplicate-issue exam into your catalog
  4. Start a sandbox for that exam, registering the example agent from the slug in the pack’s own pome.json
  5. Spawn the local examinee against those twins
  6. Finalize the run while the sandbox is still live (the one hard rule)
  7. Show the score, criteria table, and dashboard link in the chat
You stay in control: every command is plain text, shown before it runs.

Before you start

  • A coding agent that can connect to an MCP server, installed and signed in.
  • The example examinee is a small Claude Agent SDK process that runs as its own subprocess, so it needs its own Anthropic credential — an ANTHROPIC_API_KEY in your environment, or a stored claude login. Your editor’s own subscription does not cover it.
  • The walk pins the examinee to claude-haiku-4-5. Which model sits the exam is part of the experiment, not a detail: on claude-opus-5 the bundled agent passes 5 of 5 with no fix at all — it fetches the policy file by reflex — and there is nothing left to demonstrate.
  • Node 24+ with npm and npx.
  • No Pome account needed up front: the OAuth consent screen opens on the prompt’s first tool call (its step 2, moments after you paste it) — that is where you sign in or sign up, no credit card.

Install the coach skills

The skills CLI installs the Pome coach skill set from pome-sh/digital-twins into your agent’s skills directory — the installer asks which agent you are using, so pick yours there. Six skills, one job each: pome (entry router), pome-intake (scope the agent), pome-suggest-tasks (propose tasks for an agent you already have), pome-author-task (write exams), pome-verify-seed (check seed state), and pome-run-task (launch, finalize, report). Together they teach your agent the full loop. --skill '*' installs all six in one pass. Without it the installer opens a checklist with nothing ticked and you tick them one at a time; the coach only works as a set.
About the security table it prints. The installer runs third-party audits (Snyk, Socket) and shows a risk level per skill. Two things drive ours, and both are the job rather than a defect: the skills talk to the Pome MCP at mcp.pome.sh at runtime, and they hand your agent a session-scoped bearer so it can reach the twins. That bearer is minted per run, expires with the sandbox, and reaches nothing outside it. The ratings are Snyk’s and Socket’s, re-scored on their own schedule, so the level you see may differ from a colleague’s. The per-skill findings are public — read them at skills.sh/pome-sh/digital-twins.

Connect the Pome MCP

Add https://mcp.pome.sh/mcp to your coding agent as a remote HTTP MCP server. There is no API key: auth is OAuth, and the consent screen opens on the first tool call. Connect to the MCP has the wiring for each client — the one-line CLI form, the mcpServers JSON block, and what to do for a headless or managed agent. That page is where per-client configuration lives.
Every command here is plain text you can read before you run it — the install path never pipes a script into your shell and never injects remote config. There is no API key to paste: on the first tool call, your agent discovers the OAuth metadata and opens the Clerk consent screen (scopes: verify your identity, basic profile, email address). Sign in — or sign up right there — and the tools appear.

Paste the prompt

Open your coding agent anywhere (the example brings its own agent — your repo is not required) and paste:
Your agent does the rest: it seeds live GitHub + Slack twins, launches the examinee against them, waits for it to finish, finalizes, and narrates the report.
The twin tape lives in the running sandbox. finalize_run must be called while the sandbox is still live — the installed pome-run-task skill enforces this, and the prompt repeats it because a sandbox that expires first cannot be scored.

What the score means

Expect a failing run, and not a zero. Measured over five trials on claude-haiku-4-5, the bundled agent scored 25 · 25 · 25 · 50 · 67 and passed none of them. passThreshold is 100 — every criterion has to hold — so a run that routes the report to #47 fails at 25 while still getting credit for the one thing it verifiably did: it left a comment at all. The spread is the interesting part. A 25 is the agent that never opened the policy and commented on the textual match. A 50 or a 67 is the agent that reached #23 anyway — inferring it from the tracking issue’s own body — but did not name #47 in the comment, or still put #47’s link in front of the reporter. Arriving at the right place is not the same as following the rule, and the criteria do not give credit for luck. Nothing in that verdict is a matter of opinion. All five criteria are deterministic [code] checks read off the twins’ recorded calls and final state; the task declares zero [model] criteria, so the narrator has nothing to read here and nothing outside code touched the verdict. The report names which criterion failed and the state the check actually read.

The one-line fix

The whole story is one sentence, and it is the repair a builder would actually make: tell the agent where its team’s rules live. It ships behind an env switch rather than a committed edit so both arms run from one commit — two numbers measured against two different trees are not comparable. POME_TRIAGE_POLICY_HINT=on appends this to the examinee’s system prompt (policyHint() in support-triage/src/index.ts):
Before you comment on an issue or send anyone a link, read docs/triage-policy.md in the repository and follow its routing rules.
Tell your coding agent:
Same exam, same twins, same examinee commit: 0 of 5 → 5 of 5 on the recorded measurement. That loop — run, read the failure, fix, re-run — is the product.
What that sentence actually does, because it is not what it looks like. It reads as a discoverability aid, and on claude-haiku-4-5 it half is: 0 of 5 naive trials opened the policy file, 5 of 5 fixed ones did. But on claude-sonnet-5, three of four naive failures had already read it and routed to #47 anyway. A file the agent reads is data; its system prompt is instruction; and a model correctly ranks instruction above data, or anything it read could hijack it. So naming the file in the charter is not teaching the agent where to look — it is transferring authority to that file. Carry that to your own agent: if you want it to obey your team’s written conventions, you have to say so.
Why “v2” and not just “re-run”. You changed the prompt, so the thing under test is not the agent that failed — it is a second agent. Declaring agent_version is how you say so. Without it, both runs land in one run-set reporting 1 of 2 trials clean — and since neither run declared a version, the report refuses to read that as reliability: it says outright that it cannot tell one agent run twice from two different agents, and points back at agent_version. Honest, but it is a shrug where a score should be. The baseline_group_id is the other half — it pairs the two run-sets, which is what puts Compare to failing baseline on the green run-set’s page.

Open your first report

get_report prints the score, the criteria table, and the dashboard link right in your conversation. Open the link for the finalized report — and read it as a diagnosis rather than a grade. Two of the five criteria carry the story, and they fail in different places:
  • A comment containing #47 exists on issue #23 fails on GitHub’s final state. The state-diff panel shows where the comment actually landed.
  • No message containing issues/47 appears in any public channel fails on what the agent told the reporter. This is the wrong-value guard: beside asserting the right answer, it asserts the object does not hold the specific wrong value this task’s failure mode produces. It is what separates did the right thing from did the known wrong thing.
Then check the span waterfall for a get_file_contents call on docs/triage-policy.md, because it changes what the fix is. If the fetch is absent, the agent never found the rule. If it is there and the comment still landed on #47, the agent read the rule and its own standing instruction outranked it — a different problem, and one more prompt wording will not solve.

Next

Your own agent

Point Pome at your own repo and get a scored run.

Write a task

validate_tasksave_taskverify_seed — graded exams for your agent.

Evaluate an agent over MCP

The coach loop behind the paste-prompt, call by call.

Dashboard

Where runs, traces, and run handoffs live: app.pome.sh.