Skip to content

[diff view] RFC 005 4/4: production /harness route - #3

Closed
splusq wants to merge 1 commit into
rfc-005/pr3-harness-environment-runtimefrom
rfc-005/pr4-harness-production-route
Closed

[diff view] RFC 005 4/4: production /harness route#3
splusq wants to merge 1 commit into
rfc-005/pr3-harness-environment-runtimefrom
rfc-005/pr4-harness-production-route

Conversation

@splusq

@splusq splusq commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Incremental-diff view for huggingface/OpenEnv#1100.

Review and discussion happen upstream — this PR exists only because cross-fork PRs cannot chain bases, so the upstream one has to target main and its "Files changed" tab includes the PRs beneath it in the stack.

Here the base is rfc-005/pr3-harness-environment-runtime, so Files changed shows exactly this step's diff (commit 385fded4) and nothing else.

Not for merging: merging it into the fork would desync the stack.

🤖 Generated with Claude Code

Exposes a harness environment directly to clients in production mode, and
gives deployments a way to actually select that mode.

`/harness` is registered only when mode is PRODUCTION *and* the env
factory produces a `HarnessEnvironment`. Connecting opens a session and
resets the env (starting the harness and injecting tools); each
`{"type": "message", "content": ...}` frame runs one turn, streamed back
as HarnessEvent frames terminated by turn_complete. Malformed frames get
a WSErrorResponse without dropping the connection; an adapter crash
streams a terminal error event and ends the session, since harness state
after a crash is undefined.

The handler is modelled on the existing WS /mcp handler rather than the
RFC's pseudocode: it goes through `_create_session()` so capacity limits,
the AsyncExitStack, per-session executors and the idle reaper all apply.
The RFC sketch calls the factory directly and would bypass all of it.
Session activity is touched per streamed event so a long turn is not
reaped as idle.

Mode wiring: `create_app` / `create_fastapi_app` (and the web-interface
factory) take a keyword-only `mode`, resolved from `OPENENV_MODE` when
omitted. Previously `create_fastapi_app` hardcoded `register_routes(app)`,
so nothing outside tests could ever select production. Default is
unchanged (simulation), mirroring the existing `OPENENV_CLIENT_MODE`
convention on the client side.

Two notes for review:

- Harness-env detection uses a lazy import of `HarnessEnvironment` inside
  the method: `openenv.core.harness` imports env_server modules, so a
  top-level import would be circular. Detection may instantiate the
  factory once to probe it, which is safe because constructing a
  HarnessEnvironment starts nothing -- asserted by a test.
- `websocket.close()` on an already-gone client raises RuntimeError under
  TestClient but WebSocketDisconnect under a real ASGI server; both are
  now caught. Found by the end-to-end test, which drives a real uvicorn
  server. The pre-existing /mcp and /ws handlers have the same latent gap
  and are deliberately left untouched here.

Includes the end-to-end test for the whole stack: a real subprocess
harness that reads the injected MCP config, calls an env tool over the
live bridge, and streams turns -- exercised through both the simulation
step() API and a real uvicorn server's /harness socket.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@splusq

splusq commented Aug 28, 2026

Copy link
Copy Markdown
Owner Author

Closing: this was only a diff view, and an un-mergeable PR in the list is more confusing than the cumulative diff it was working around. Review happens on the upstream PR.

@splusq splusq closed this Aug 28, 2026
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.

1 participant