Skip to content

fix(v1): persist prime-agent ACP sessions - #2260

Draft
parkerpettit9 wants to merge 14 commits into
feat/prime-agent-harnessfrom
fix/prime-agent-persistent-acp
Draft

fix(v1): persist prime-agent ACP sessions#2260
parkerpettit9 wants to merge 14 commits into
feat/prime-agent-harnessfrom
fix/prime-agent-persistent-acp

Conversation

@parkerpettit9

@parkerpettit9 parkerpettit9 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Changes

  • Use one live ACP process for each trace.
  • Preserve Prime Agent and IPython state across interaction turns.
  • Isolate the agent directory, daemon socket, temporary directory, and registry for each trace.
  • Hash trace IDs before using them in state paths.
  • Bind install locks to a PID and Linux process start time.
  • Upgrade Prime Agent to 0.7.0 and verify the release tarball SHA-256.
  • Keep the interception key out of configuration files.
  • Pass the system prompt once.
  • Validate the supported Prime Agent options.
  • Stop and remove only the current trace state during cleanup.
  • Add live session and security regression tests.

Tests

  • uv run pytest tests/v1 -m "not e2e" -q: pass.
  • Prime Agent security regressions: 3 passed.
  • Prime Agent ACP resume in Docker: passed after the path and lock fixes.
  • Terminal-Bench 2.1 with GPT-5.6 Luna on Prime and Docker: both harness traces completed without infrastructure errors. Both received reward 0.
  • Pre-push Ruff, format, and Ty checks: pass.

Base

This PR targets #2254. The session implementation uses the Harness.session and ACP.session APIs already merged into main.

sethkarten and others added 11 commits August 4, 2026 21:37
Drives prime-agent's own ACP mode through the existing ACP helper rather than
the pi harness's third-party pi-acp adapter. That adapter spawns `pi --mode rpc`
and hard-codes pi's RPC command and event union, so prime-agent's IPython-only
tool model, subagents, autonomous gates, goals, and heartbeats either degrade to
a generic tool call or disappear.

prime-agent speaks ACP natively as of its ACP mode, and carries the concepts ACP
has no field for in a namespaced `ai.primeintellect.prime-agent` `_meta`
envelope, so a rollout can observe them without the harness parsing a private
protocol.

Targets the current launch() contract. HOME is pinned per trace because
prime-agent writes session and kernel state beneath it and concurrent rollouts
must not share either.
0.6.0 is the first Prime Agent release that ships native ACP mode, so the
harness can now install a published tarball that actually has --mode acp.
Verified the derived tarball URL returns 200.
… key

Four fixes found by running an actual eval in the docker runtime, each verified
in a container rather than inferred:

- Containers ship no Node and prime-agent requires >=22.8, so install failed with
  "npm: not found". Bootstraps Node the way the pi harness does, and exports it on
  PATH for the launch wrapper too, since the bundled Node is not on the container
  PATH.
- The published release derives its env prefix from its own package piConfig, so
  it reads PRIME_AGENT_CODING_AGENT_DIR, not the upstream PI_ prefix. With the
  wrong name models.json was ignored and the run failed with
  "Unknown provider intercept".
- prime-agent does not expand "$VAR" in models.json: it sends the literal string
  as the bearer token, which produced "401 unauthorized". Confirmed against a
  capturing HTTP server, which received `Bearer $PRIME_AGENT_INTERCEPT_KEY`.
  Inlines the secret instead of the pi-style indirection.

With these, an eval completes end to end: 4 model calls, err 0.00, and a scored
alphabet_sort reward.
…he prompt

Review follow-up on two real problems.

The bearer token was written in plaintext to the per-trace models.json. Concurrent
rollouts share a runtime, so model-executed code in one rollout could read another
rollout's credential and issue authenticated requests against its interception
endpoint. This was a consequence of inlining the secret to work around prime-agent
not expanding "$VAR": the pi harness's indirection had kept it out of the file.
models.json now carries a placeholder, and the launch wrapper substitutes the real
value from the environment at exec time under a 0700 dir and a 0600 file.

The system prompt was applied twice: once via --append-system-prompt and again by
the ACP runner, which seeds it into the conversation for a new session. Dropped
the flag and left a note so it does not come back.

Verified by rerunning the eval: ok=true, 3 model calls, 0 errors, and a scored
alphabet_sort reward.
…Alpine

The install guard short-circuited on the binary alone, so a runtime that
already held one build reused it after `version` or `tarball_url` changed.
Key the guard on the requested tarball like the pi harness keys on its
versions, and give the Alpine branch the same repo-bump retry, since the
official Node build is glibc-only and an older Alpine's own nodejs-current
is below the 22.8 prime-agent needs.
…have

prime-agent's ACP mode ignores the `mcpServers` of `session/new` entirely, and
its own MCP integrations are authored Python skills the model imports in its
kernel, so tool servers handed to the harness never reached the model: the
repo's own echo-acp-resume-v1 fixture ran to completion with the agent
reporting the tool did not exist and the reward at 0. Declare SUPPORTS_MCP
false so `validate_pairing` rejects that pairing instead of degrading it.
…t segment

A resumed segment replays the accreted conversation, and the ACP runner renders
that transcript into the prompt with the `[system]` block the first segment
already rendered into it, so passing `system_prompt` again delivered the task
instructions twice. Observed on echo-user-sim-v1: the second segment's prompt
carried two copies of the system prompt, one after this change.
…arly

Three install/launch edges from review, none reachable on the images this runs
on today but all of them failing obscurely when they are hit:

- the wrapper substituted the bearer token with `sed`, so a token containing
  `|`, `&`, or a backslash would corrupt the key or abort the wrapper before
  exec; node now rewrites the parsed models.json instead. Today's secret is
  `secrets.token_urlsafe(16)`, which cannot contain those, so this is about not
  depending on the generator's alphabet.
- a curl-less non-Debian image ran `apt-get` regardless and failed three steps
  later inside `tar` ("tar: invalid magic"); it now says what it needs.
- an unrecognized machine fell back to the x64 Node archive and failed as
  "prime-agent requires Node.js 22.8 or newer"; it is now rejected by name,
  like the OS check already does.
The bucket URL reads like a stale internal endpoint next to the user-facing
installer at app.primeintellect.ai/prime-agent/install.sh, so note why the harness
uses it. That script is a thin front end: it defaults its own prime_agent_base_url
to this bucket and downloads $base/releases/v$version/$package-$version.tgz, the
same shape _tarball() builds. The value is also the prime-agent repo's
R2_PUBLIC_BASE_URL variable, which its release workflow publishes to. This harness
installs the npm tarball directly instead of running the script, so it needs the
artifact base rather than the installer URL.

Comment only; no behavior change. Verified the derived URL for the pinned version
returns 200, and the docker eval still reports ok=true with 4 model calls, no
errors, and a scored reward.
Comment thread verifiers/v1/harnesses/prime_agent/harness.py
Comment thread verifiers/v1/harnesses/prime_agent/harness.py Outdated
Comment thread verifiers/v1/harnesses/prime_agent/harness.py Outdated
@hallerite
hallerite force-pushed the feat/prime-agent-harness branch from a0681ae to f9513af Compare August 5, 2026 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants