Add first-class OpenClaw support via an isolated provider overlay
- Dominant language
- Rust
- Stars
- 26
- Forks
- 6
- Avg merge
- 1h 13m
- Merged PRs (30d)
- 384
Description
## Summary
Add first-class, configuration-first OpenClaw support so users can run its local agent loop through Pentect without permanently changing their OpenClaw configuration.
This is the focused implementation issue for the OpenClaw item in #114. OpenClaw's native Codex runtime remains a separate surface and is **not** covered by this issue.
## User experience
Target command:
```sh
pentect openclaw --model openai/gpt-5 --
```
For an explicit compatible upstream:
```sh
pentect openclaw \
--api responses \
--model openai/gpt-5 \
--upstream https://api.openai.com/v1 \
--
```
Pentect should:
1. start the existing local protocol gateway;
2. create an owner-only temporary OpenClaw state/config overlay;
3. add a temporary `pentect` model provider whose `baseUrl` points at the local gateway and whose API is one of OpenClaw's documented provider APIs;
4. select the temporary provider/model for the child process;
5. launch OpenClaw with the isolated state;
6. restore the process environment and remove temporary state on normal exit, error, signal, or partial startup failure.
No plaintext upstream credential may be written to the temporary config, command line, logs, or diagnostics.
## Scope
### Phase 1: local, foreground agent loop
Support the documented custom-provider paths already covered by Pentect's protocol adapters:
- OpenAI Chat Completions (`openai-completions`)
- OpenAI Responses (`openai-responses`)
- Anthropic Messages (`anthropic-messages`)
Cover prompt text, streaming, completed tool calls, tool results, MCP/browser-produced content, errors, retries, cancellation, and supported files/images.
### Explicitly out of scope
- OpenClaw's native Codex runtime (use and test the existing Codex integration separately)
- background messaging, cron, daemon, or Gateway jobs that outlive the launched child
- remote VPS/Docker/SSH execution unless Pentect is installed on that execution host
- arbitrary provider protocols that Pentect does not already parse
- permanent edits to the user's `openclaw.json`, auth profiles, workspace, or skill directories
- claiming all OpenClaw channels/surfaces are protected based only on a CLI smoke test
## Proposed implementation
### 1. Add the client descriptor
In `crates/pentect-cli/src/client_descriptor.rs`:
- add an `OPENCLAW` descriptor;
- default executable: `openclaw`;
- path override: `--openclaw`;
- expose it through `CLIENTS`;
- model the launcher as a dedicated config-overlay injection rather than treating OpenClaw as Codex or a generic environment-only client.
A dedicated launcher is preferable because OpenClaw has its own state directory, provider catalog, model selection, and long-running Gateway modes.
### 2. Build an isolated OpenClaw config overlay
Add `crates/pentect-cli/src/openclaw.rs` (or equivalent) that:
- resolves the effective OpenClaw state directory using its documented environment/config rules;
- reads the existing config as untrusted input and validates only the fields needed for provider/model discovery;
- creates a new owner-only temporary state directory using the existing secure temporary-directory helpers;
- preserves required non-secret settings by copy/overlay, while replacing the selected model provider with a Pentect-owned provider;
- sets the temporary provider `baseUrl` to the local Pentect gateway;
- uses a non-secret loopback credential for OpenClaw → Pentect authentication;
- passes the temporary state location only to the child process;
- rejects child arguments or environment values that can override the protected provider, base URL, state directory, or selected model after validation.
Prefer a minimal overlay or schema-aware merge. Do not recursively copy caches, sessions, logs, downloaded skills, or credential stores.
### 3. Preserve upstream identity and credentials safely
- discover the original provider, base URL, API type, and selected model before inserting Pentect;
- reuse the existing `--upstream`, `--upstream-header-env`, CA certificate, and client identity handling;
- forward provider credentials from process-local environment/auth handling without serializing their values;
- remove credential environment variables from the child when the temporary Pentect provider no longer needs them;
- fail closed when the selected OpenClaw provider uses an unsupported wire protocol or when its credential cannot be forwarded safely;
- bind file attestations/handle restoration to the effective upstream credential scope exactly as existing gateways do.
If OpenClaw auth profiles cannot be consumed without copying a secret into temporary state, keep that auth mode out of Phase 1 and document the supported API-key environment path.
### 4. Reuse protocol adapters; do not add an OpenClaw wire protocol
Route by the declared OpenClaw provider API:
| OpenClaw API | Pentect adapter |
| --- | --- |
| `openai-completions` | OpenAI Chat Completions |
| `openai-responses` | OpenAI Responses |
| `anthropic-messages` | Anthropic Messages |
Unknown or mismatched request/stream formats remain blocked by default. OpenClaw-specific code should own only launch/config lifecycle and capability declaration.
### 5. Handle process lifecycle and long-running modes
- forward exit status and signals consistently with the other launchers;
- clean temporary state after child exit and on startup rollback;
- detect commands that start detached/background Gateway work and reject them in protected one-shot mode with a clear message;
- do not advertise protection when the actual model request originates in another container/VM/host;
- document that a future managed local gateway requires a separate design for authentication, lifetime, and remote access.
### 6. Tests
#### Unit tests
- provider/API → Pentect adapter mapping;
- schema-aware config merge and model selection;
- existing config is not mutated;
- secrets never appear in generated config, argv, errors, or logs;
- owner-only permissions and cleanup;
- rejection of provider/base URL/state overrides;
- unsupported APIs fail before child launch;
- startup failure restores environment and removes temporary state.
#### Protocol fixtures
For all three declared APIs:
- non-streaming and streaming text;
- incremental and completed tool calls;
- tool results containing a synthetic secret;
- MCP/browser-produced content;
- malformed content and unknown event types;
- provider errors, retry, cancellation, and interrupted streams;
- supported image/file inputs.
Assert that the upstream receives opaque handles, ordinary assistant text is never restored, and restoration happens only in a recognized local completed-tool boundary.
#### Pinned client smoke/E2E
- install a pinned OpenClaw release in CI;
- launch the real binary through the release Pentect binary;
- run against provider-shaped mock servers for Chat, Responses, and Messages;
- add one authenticated live E2E with synthetic secrets before marking OpenClaw verified;
- record the exact OpenClaw version and covered surface in `COMPATIBILITY.md`.
### 7. Documentation and release evidence
Update:
- `COMPATIBILITY.md`
- `tools/client_smoke.py`
- generated client/reference docs and navigation
- install/quick-start examples
- troubleshooting for background/remote execution and unsupported auth modes
- release workflow/package fixtures for the pinned OpenClaw version
Only add OpenClaw to the supported table after the release gate and authenticated synthetic-secret E2E pass.
## Acceptance criteria
- [ ] `pentect openclaw` launches a pinned OpenClaw version through an isolated, temporary provider configuration.
- [ ] The user's OpenClaw config, auth profiles, workspace, skills, sessions, and caches are unchanged.
- [ ] Chat Completions, Responses, and Anthropic Messages each have request/stream/tool fixtures.
- [ ] The upstream observes handles instead of synthetic secrets.
- [ ] Handles are restored only for recognized local completed tool calls.
- [ ] Temporary config, argv, environment passed to the child, logs, and diagnostics contain no upstream plaintext credential.
- [ ] Unsupported provider APIs and protected-routing overrides fail closed before launch.
- [ ] Background, remote, native Codex, and unverified channel surfaces are clearly excluded.
- [ ] CI pins the tested OpenClaw version and release evidence updates the compatibility table.
- [ ] Documentation includes quick start, supported auth/provider modes, limitations, and recovery steps.
## Open questions to resolve before coding
1. Which OpenClaw state-dir override is stable for an isolated child without hiding required workspace configuration?
2. Can OpenClaw auth-profile credentials be forwarded process-locally without copying secret material, or should Phase 1 support environment-based API keys only?
3. Does OpenClaw allow selecting an injected provider/model entirely through the overlay, or must protected CLI arguments be added and sanitized?
4. Which commands create work that outlives the child, and how can they be detected reliably before launch?
5. Should the first release include all three APIs, or land OpenAI Chat/Responses first and add Anthropic after its authenticated E2E?
## References
- Roadmap: #114, section “Hermes and OpenClaw”
- OpenClaw skills and workspace loading: https://docs.openclaw.ai/tools/skills
- OpenClaw model-provider configuration: https://docs.openclaw.ai/concepts/model-providers
- OpenClaw gateway configuration: https://docs.openclaw.ai/gateway/config-tools
- Pentect compatibility contract: `COMPATIBILITY.md`
Contributor guide
Research direction
Start by reading crates/pentect-cli/src/client_descriptor.rs, the existing launcher and secure temporary-directory helpers, then inspect tools/client_smoke.py and COMPATIBILITY.md. Add the isolated OpenClaw launcher and its lifecycle, protocol, security, and fixture tests without mutating user state. Done means pinned smoke/E2E coverage, release evidence, and documentation for supported modes and exclusions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- cli, documentation, security, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100