Research: Codex, pi, Copilot and Cursor developers on the agent host
Research done 2026-10-14 against agento11y plugins/agento11y/v0.49.0 (the version this demo pins), Codex rust-v0.162.1, pi 1.2.0 with @grafana/agento11y-pi 0.25.0, Copilot CLI v1.0.97 and Cursor CLI 2026.10.14-0f9edde. Items marked UNVERIFIED need a spike. Re-check anything version-sensitive before relying on it.
Canonical sources
- Grafana: Instrument coding agents. It defers per-agent detail to
plugins/<agent>/README.mdin grafana/agento11y. These two are authoritative over inference from plugin source. - From the Grafana guide:
- Non-interactive setup means writing
~/.config/agento11y/config.env, or runningagento11y login --endpoint --tenant --token-stdin --otlp-endpoint. agento11y <agent> install --jsonexists for claude, copilot, opencode and pi, andagento11y agents reconcileregisters several at once.- Codex is excluded from that managed install because it needs a one-time hook trust step.
- Non-interactive setup means writing
- The app has a built-in Coding agents view: sessions, cost, tokens and tools, by agent, user, repo and branch. Suffixed names such as
claude-code/xroll up under the base agent.
Decisions taken (maintainer, 2026-10-14)
- Scope: Codex and pi are implemented now. Copilot and Cursor are gated behind a go/no-go spike that the maintainer signs off.
- Model access: a scoped Bedrock credential (new IAM principal) in the agent-host secret.
- No loop budgets, no AWS Budgets alarm and no data-residency constraint: this is a demo environment.
- Neither agent can use the Claude apps gateway: it has no unattended auth and serves only Anthropic Messages.
- Developer containers cannot reach IMDS, and that stays true.
- Hosting: same agent host. All
render.pyand seam changes land together, with one planned host replacement at release.
Cross-cutting facts
- Host replacement.
agent-host/render/render.py,agent-host/host/*andagent-host/config/*are in the root-run bundle, and their SHA-256s are in user_data. Editing any of them, or bumpingimages.tag, replaces the EC2 host. That resets the gateway Postgres ledger and forces Claude developers to sign in again. The new knobs and the developer list live in the secret’sconfigkey and do not replace the host. - No gateway env push. For non-Claude developers, the
AGENTO11Y_*env thatgateway_configsends Claude Code today must come from the container. Write~/.config/agento11y/config.env; Codex hooks run with a stripped environment, so the file is required there. - Agent name. The plugin READMEs say not to put a
/in a non-Claude agent name, because a slash marks a subagent. Guard calls carry no tags, so rules can scope to the demo only by agent name.- Trade-off: a demo-scoped name such as
codex-touchlineshows as its own row in the Coding agents view. - Codex suggests
codex-<prefix>. The pi spike usedpi/touchlinesuccessfully. - Pick one convention for all new agents.
- Trade-off: a demo-scoped name such as
- Auto coding-agent tags. Sessions run in
mktemp -dcheckouts with noorigin, sorepoandbranchwould be unbounded label values. Set staticAGENTO11Y_TAGS(service.namespace,team), and enableuserat most. - Tool-name vocabulary. The guard rules in
terraform/grafana-agento11y.tfuse Claude names (Bash(...),Read(...),Edit(...),Write(...),Grep(...),WebFetch). New agents differ, and case-sensitivity ofblocked_toolsmatching is UNVERIFIED. - Dashboards.
terraform/dashboards/claude-code.json.tftpland the alert and recording rules are built on Claude Code’s nativeclaude_code_*metrics. None of the new agents emit those. The built-in Coding agents view is the first-cut surface; per-agent dashboards are optional follow-ups. - Dev session scripts are Claude-specific.
apps/dev-workstation/bin/dev-sessionusesclaude -p,--allowedTools,total_cost_usd,permission_denialsand ablocked by hookgrep. The prompt corpus is agent-neutral, and its picking, follow-up, abandon and PII-burst logic can be shared.
Codex
- Plugin.
plugins/codexv0.5.0 is experimental and hook-based (SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop).- It emits one generation per turn, not one per model call; intermediate assistant text and reasoning text are lost.
- Tokens are read from the rollout JSONL, so never use
codex exec --ephemeral. - Preflight deny works (UserPromptSubmit), and so do postflight deny and redaction (PreToolUse with
updatedInput). - Hooks cover
Bash,apply_patch(matcher aliasesEditandWrite) andmcp__server__tool. Hosted tools such as WebSearch are not hooked.
- Hook trust headless (preferred route).
- Define the five hooks inline in the root-owned system layer
/etc/codex/config.toml, baked into the image. System-layer hooks are “managed” and trusted by policy. - Mirror
plugins/codex/hooks/hooks.jsonat the pinned tag, and add a CI check that the two stay in sync. - Fallback:
--dangerously-bypass-hook-truston everycodex execandcodex exec resume. - Both UNVERIFIED in
codex exec.
- Define the five hooks inline in the root-owned system layer
- Headless.
codex exec --jsonreturns JSONL withthread.startedandturn.completed(usage); follow-ups usecodex exec resume <id>.- Codex’s own sandbox likely fails under
cap_drop: ALL, so run--sandbox danger-full-accessinside the isolated container. - No login bot.
- Model.
- Use the built-in
amazon-bedrockprovider, with OpenAI models (openai.gpt-5.6-luna,-terra,-sol,openai.gpt-5.5) onbedrock-mantle, authenticated byAWS_BEARER_TOKEN_BEDROCKor SigV4 keys. - Mantle availability may be US regions only, and a US region is acceptable.
- Application inference profiles are not supported on mantle.
- IAM action:
bedrock-mantle:CreateInference. - The OpenAI help article warns that MCP namespace tools and tool search are limited on Bedrock, and 14 of 53 prompts touch MCP.
mapperutil.InferProviderdoes not recognise theopenai.prefix, so the provider falls back tocodexand cost may be missing. A small upstream fix is possible.
- Use the built-in
- Native OTel.
[otel]inconfig.toml, OTLP/HTTP with a literal Basic auth header. The seedconfig.tomlis rendered from a secret file.- Metrics include
codex.turn.token_usage,codex.turn.cost_microusdandcodex.tool.call; Prometheus names are UNVERIFIED. - Codex logs need
logs:write, whichagento11y_client_tokenlacks. Use a separate scoped token, because the ingest token must never enter a developer container. - Set
analytics.enabled=false,check_for_update_on_startup=falseand cumulative temporality.
- Install. Pinned
codex-package-<arch>-unknown-linux-musl.tar.gzfrom the release, plusSHA256SUMSand a sigstore bundle. It is Apache-2.0, so it can be baked into the image. - Sources:
pi
- Upstream. pi moved to
earendil-works/pi, and npm moved to@earendil-works/*. Since 0.99.0 it has built-in MCP (stdio and streamable HTTP,~/.pi/agent/mcp.json); set"exposure": "direct"so tools appear asmcp__server__tool. - Plugin.
@grafana/agento11y-piis an in-process extension loaded withpi -e <dir>. It emits one generation per turn, with tokens, cost from pi’s own price catalog, content, tags and tool spans.- Verified in a local spike on pi 1.2.0: print and JSON modes load it, generations export, and a postflight deny blocks
bash. - Preflight deny does not stop the model call (a documented gap, grafana/agento11y#861). Preflight transform and redaction does work, on every model call.
- Reasoning tokens are dropped (#825).
- The plugin is tested upstream against pi 0.87.1. Pin both pi and the plugin, and re-spike on every bump.
- Headless.
- Run
pi --mode json ... </dev/null; it hangs if stdin is left open. Follow-ups reuse--session-id. - Set
PI_TELEMETRY=0,PI_OFFLINE=1andPI_SKIP_VERSION_CHECK=1. - No permission system, so
bashis unrestricted and only the container isolation and the guards bound it. - No login.
- Run
- Model.
- Direct Bedrock with the scoped key, against the existing per-team application inference profiles (
data.aws_iam_policy_document.bedrock_invoke). - For custom ARN model ids,
models.jsonneeds explicitcost, orcost_usdis 0. Whether pi routes profile ARNs correctly is UNVERIFIED.
- Direct Bedrock with the scoped key, against the existing per-team application inference profiles (
- Install. Lockfile-pinned
npm ci --ignore-scriptsin the image, before the step that removes npm. Do not useagento11y pi install --json, which installs the plugin unpinned. - Guards. The hook sends
agent_nameas configured and lowercase tool names (bash,{"command": ...}). - Sources:
- https://github.com/earendil-works/pi (
packages/coding-agent/docs/) - https://pi.dev/news/2026/5/7/pi-has-a-new-home
plugins/pi/README.md
- https://github.com/earendil-works/pi (
Copilot (gated)
- Surface. Copilot CLI (
copilot). The plugin is hook-based;agento11y copilot install --jsonwrites~/.copilot/hooks/agento11y.json. - Plugin.
- One generation per turn at
agentStop, read from~/.copilot/session-state/<id>/events.jsonl. Token data may be partial. - No preflight guards. Postflight deny works, and redaction works on the CLI surface.
AGENTO11Y_USER_IDis required.
- One generation per turn at
- Headless.
- Run
copilot -p --no-ask-user --allow-tool/--deny-tool --output-format jsonwithCOPILOT_GITHUB_TOKEN. - The token can be a fine-grained PAT with the Copilot Requests permission, owned by a personal account. Classic PATs are not supported.
- No login bot.
- UNVERIFIED: whether hooks fire in
-pmode, and whether-pcan resume a session.
- Run
- Model.
- GitHub-hosted only, which needs Copilot seat(s) billed in GitHub AI Credits, with overage on by default.
- BYOK supports
openai,azureandanthropicprovider types, but not Bedrock.
- Native OTel.
COPILOT_OTEL_ENABLED, OTLP/HTTP, GenAI semantic conventions; no cost attribute. - Blockers needing the maintainer.
- The identity model: one shared identity or one per persona.
- Seats.
- Whether a 24/7 synthetic loop is acceptable under GitHub’s terms and abuse detection; no official statement was found.
- Sources:
Cursor (gated)
- Surface.
cursor-agentCLI, which works on Linux arm64. The plugin is hook-based (agento11y cursor installwrites~/.cursor/hooks.json) and is written for the IDE first. - Blocker. In headless
agent -pmode Cursor does not emitbeforeSubmitPrompt,afterAgentResponseorstop(per Cursor staff, 2026-08). The result has no prompt, assistant text or tokens, no preflight guard, andgeneration_id == conversation_id. A Linux arm64 report also has hooks failing silently.- Workarounds:
- accept capture limited to tool spans;
- evaluate a wrapper over
--output-format stream-jsonthat emits generations via the agento11y SDK; token usage remains UNVERIFIED because the current official output schema does not document it; - wait for Cursor to fix it.
- Workarounds:
- Model. Always Cursor’s hosted backend, which needs paid Cursor seat(s) or Enterprise service accounts. Bedrock BYOK is documented for the IDE only. No per-session budget.
- Install. A tarball from
downloads.cursor.comwith no published checksum or signature. Redistribution terms are unknown, so install at container start rather than baking it into the public image. - Sources:
Maintainer decisions and refresh, 2026-10-15
- Keep the existing demo stack destination.
- Copilot: use the existing seat for a bounded spike only; continuous synthetic traffic requires a separate decision after results.
- Cursor: defer deployment. Resume after a pinned headless release proves the required lifecycle and token fields, or an explicit decision accepts incomplete capture. Current output-format documentation does not establish token usage; the earlier stream-json usage claim was unverified.
- SDK JS 0.13.0 and CLI/plugin 0.49.0 remain the latest stable releases, verified against GitHub releases and npm. Retain pins; use
agento11y doctor --require-cloudfor live validation. CLI 0.49.0 anonymous statistics are disabled explicitly in the demo image.