docs: expand Claude contractor design
This commit is contained in:
436
docs/claude/ARCHITECTURE.md
Normal file
436
docs/claude/ARCHITECTURE.md
Normal file
@@ -0,0 +1,436 @@
|
||||
# Claude Contractor Architecture
|
||||
|
||||
## Purpose
|
||||
|
||||
Describe the phase 1 architecture for integrating Claude Code into OpenClaw as a contractor-backed agent.
|
||||
|
||||
This document assumes the phase 1 decisions already made:
|
||||
|
||||
- Claude only, Gemini deferred
|
||||
- plugin-owned CLI root: `openclaw contractor-agents ...`
|
||||
- contractor-backed agents use a custom primary model
|
||||
- that custom model bridges OpenClaw turns into Claude Code sessions
|
||||
|
||||
## High-level architecture
|
||||
|
||||
```text
|
||||
User / Channel
|
||||
↓
|
||||
OpenClaw routing + agent selection
|
||||
↓
|
||||
Agent primary model = contractor-claude-bridge
|
||||
↓
|
||||
ContractorAgent plugin
|
||||
├─ contractor metadata resolver
|
||||
├─ session map store
|
||||
├─ Claude ACP adapter
|
||||
├─ input filter / context reducer
|
||||
└─ response normalizer
|
||||
↓
|
||||
Claude Code session
|
||||
```
|
||||
|
||||
## Core architectural principle
|
||||
|
||||
OpenClaw remains the outer control plane.
|
||||
Claude Code remains the live reasoning runtime.
|
||||
|
||||
That means:
|
||||
|
||||
### OpenClaw owns
|
||||
|
||||
- agent registration
|
||||
- workspace ownership
|
||||
- routing and channel bindings
|
||||
- visible transcript/session files
|
||||
- permissions and approvals
|
||||
- plugin loading and bridge model selection
|
||||
|
||||
### Claude Code owns
|
||||
|
||||
- live session continuity
|
||||
- evolving reasoning context for a contractor task
|
||||
- internal coding workflow and execution trajectory
|
||||
|
||||
The plugin exists to bridge those two worlds without forcing both systems to maintain full independent copies of the same conversation state.
|
||||
|
||||
## Main components
|
||||
|
||||
## 1. Contractor metadata resolver
|
||||
|
||||
This component determines whether the current agent is a contractor-backed Claude agent and, if so, what runtime settings apply.
|
||||
|
||||
Expected inputs:
|
||||
|
||||
- OpenClaw agent id
|
||||
- agent config entry
|
||||
- plugin config defaults
|
||||
|
||||
Expected outputs:
|
||||
|
||||
- whether contractor runtime is enabled
|
||||
- contractor kind, currently `claude`
|
||||
- bridge model id
|
||||
- backend type, likely ACP
|
||||
- runtime mode, likely persistent
|
||||
- workspace path
|
||||
|
||||
### Proposed config direction
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "contractor-dev",
|
||||
workspace: "/workspace/contractor-dev",
|
||||
model: "contractor-claude-bridge",
|
||||
runtime: {
|
||||
type: "contractor",
|
||||
contractor: {
|
||||
kind: "claude",
|
||||
backend: "acp",
|
||||
mode: "persistent"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The exact config location can still evolve, but the architecture assumes there is a stable way to resolve contractor runtime settings from agent identity.
|
||||
|
||||
## 2. Bridge model
|
||||
|
||||
The bridge model is the primary execution seam inside OpenClaw.
|
||||
|
||||
Suggested model id:
|
||||
|
||||
- `contractor-claude-bridge`
|
||||
|
||||
### Why it exists
|
||||
|
||||
OpenClaw expects a primary model for each agent. The bridge model satisfies that contract while redirecting actual reasoning work to Claude Code.
|
||||
|
||||
### What it does
|
||||
|
||||
- receive the agent turn as a model request
|
||||
- identify the target OpenClaw agent and session
|
||||
- resolve contractor metadata
|
||||
- call the session map store
|
||||
- call the Claude ACP adapter
|
||||
- normalize Claude output into an OpenClaw model response
|
||||
|
||||
### What it does not do
|
||||
|
||||
- behave like a normal stateless LLM provider
|
||||
- replay the full OpenClaw prompt envelope every turn
|
||||
- replace OpenClaw routing or channel delivery
|
||||
|
||||
## 3. Session map store
|
||||
|
||||
This component persists the mapping between OpenClaw sessions and Claude sessions.
|
||||
|
||||
Suggested location:
|
||||
|
||||
```text
|
||||
<agent-workspace>/.openclaw/contractor-agent/session-map.json
|
||||
```
|
||||
|
||||
Suggested record shape:
|
||||
|
||||
```ts
|
||||
type SessionMapEntry = {
|
||||
openclawSessionKey: string
|
||||
agentId: string
|
||||
contractor: "claude"
|
||||
claudeSessionId: string
|
||||
workspace: string
|
||||
createdAt: string
|
||||
lastActivityAt: string
|
||||
state: "active" | "closed" | "orphaned"
|
||||
}
|
||||
```
|
||||
|
||||
### Responsibilities
|
||||
|
||||
- lookup mapping by OpenClaw session key
|
||||
- create mapping after first successful Claude session creation
|
||||
- update timestamps and state
|
||||
- mark sessions orphaned on recoverable failures
|
||||
- remove or replace mappings during reset flows
|
||||
|
||||
### Non-responsibilities
|
||||
|
||||
- storing full conversation text
|
||||
- storing OpenClaw config
|
||||
- being the canonical transcript source
|
||||
|
||||
## 4. Input filter and context reducer
|
||||
|
||||
This is one of the most important parts of the architecture.
|
||||
|
||||
The bridge model should not forward full OpenClaw-managed input blindly to Claude Code. Instead it should convert the incoming turn into a contractor payload.
|
||||
|
||||
### Contractor payload should include
|
||||
|
||||
- latest user message
|
||||
- OpenClaw session key
|
||||
- agent id
|
||||
- workspace path
|
||||
- minimal runtime hints needed by Claude
|
||||
|
||||
### Contractor payload should exclude or heavily reduce
|
||||
|
||||
- repeated OpenClaw prompt wrappers
|
||||
- large historical message dumps already represented in Claude session state
|
||||
- redundant policy text already injected at Claude session creation
|
||||
|
||||
### Why this matters
|
||||
|
||||
Without this reducer, the system drifts into dual-context management:
|
||||
|
||||
- OpenClaw reconstructs context every turn
|
||||
- Claude maintains its own session context
|
||||
- both copies diverge over time
|
||||
|
||||
The reducer prevents that by making Claude the primary owner of live context after bootstrap.
|
||||
|
||||
## 5. Claude ACP adapter
|
||||
|
||||
This component talks to Claude Code through the chosen ACP/runtime path.
|
||||
|
||||
Architecture assumption for phase 1:
|
||||
|
||||
- Claude Code is hosted through OpenClaw-compatible ACP infrastructure
|
||||
- the plugin uses persistent Claude sessions whenever possible
|
||||
|
||||
### Responsibilities
|
||||
|
||||
- create new Claude sessions
|
||||
- resume existing Claude sessions
|
||||
- send new user messages to Claude
|
||||
- collect Claude output
|
||||
- surface recoverable failures to the bridge model
|
||||
|
||||
### Expected operations
|
||||
|
||||
- `createSession(...)`
|
||||
- `resumeSession(...)`
|
||||
- `sendMessage(...)`
|
||||
- `closeSession(...)`
|
||||
- `healthCheck(...)`
|
||||
|
||||
Exact API shape depends on implementation details and available runtime hooks.
|
||||
|
||||
## 6. Response normalizer
|
||||
|
||||
Claude output may not match the exact shape OpenClaw expects from a model provider. The normalizer converts it into the response format used by the bridge model.
|
||||
|
||||
### Responsibilities
|
||||
|
||||
- convert plain assistant text
|
||||
- preserve useful structured output if present
|
||||
- flatten multi-part response payloads where needed
|
||||
- translate adapter/runtime failures into OpenClaw-visible model errors
|
||||
|
||||
### Desired outcome
|
||||
|
||||
From OpenClaw's point of view, the result should feel like a normal model completion even though it came from a stateful Claude session.
|
||||
|
||||
## Turn lifecycle
|
||||
|
||||
## A. Agent provisioning lifecycle
|
||||
|
||||
Triggered by:
|
||||
|
||||
```bash
|
||||
openclaw contractor-agents add --agent-id <agent-id> --workspace <workspace> --contractor claude
|
||||
```
|
||||
|
||||
Flow:
|
||||
|
||||
1. create OpenClaw agent with model `contractor-claude-bridge`
|
||||
2. write contractor runtime metadata to agent config
|
||||
3. create contractor state directory
|
||||
4. initialize empty session map store
|
||||
|
||||
No Claude session is required at provisioning time.
|
||||
|
||||
## B. First conversation turn
|
||||
|
||||
1. OpenClaw routes message to contractor-backed agent
|
||||
2. OpenClaw invokes primary model `contractor-claude-bridge`
|
||||
3. bridge model resolves agent metadata
|
||||
4. bridge model checks session map for current OpenClaw session
|
||||
5. no mapping found
|
||||
6. bridge model asks Claude ACP adapter to create a new Claude session
|
||||
7. plugin injects bootstrap instructions and minimal OpenClaw metadata
|
||||
8. plugin sends latest user message
|
||||
9. Claude replies
|
||||
10. plugin stores mapping and returns normalized output to OpenClaw
|
||||
|
||||
## C. Later conversation turns
|
||||
|
||||
1. OpenClaw invokes `contractor-claude-bridge`
|
||||
2. metadata resolver confirms contractor-backed Claude agent
|
||||
3. session map returns mapped Claude session id
|
||||
4. input reducer extracts newest actionable message
|
||||
5. Claude ACP adapter resumes session and sends message
|
||||
6. Claude replies
|
||||
7. response normalizer emits OpenClaw model response
|
||||
8. session map timestamp is updated
|
||||
|
||||
## D. Reset flow
|
||||
|
||||
If the user resets the session:
|
||||
|
||||
1. plugin invalidates or replaces mapping for the OpenClaw session key
|
||||
2. next turn creates a fresh Claude session
|
||||
3. bootstrap instructions are injected again
|
||||
|
||||
Recommended behavior:
|
||||
|
||||
- keep OpenClaw agent and workspace stable
|
||||
- replace only contractor session continuity
|
||||
|
||||
## E. Recovery flow
|
||||
|
||||
If Claude session is missing or unusable:
|
||||
|
||||
1. mark mapping as `orphaned`
|
||||
2. create a new Claude session
|
||||
3. inject bootstrap instructions
|
||||
4. optionally pass a minimal recovery summary derived from recent OpenClaw-visible context
|
||||
5. replace mapping
|
||||
|
||||
This should be treated as a degraded fallback path, not the normal operating path.
|
||||
|
||||
## Bootstrap strategy
|
||||
|
||||
Bootstrap text should be injected when a Claude session is first created.
|
||||
|
||||
It should include:
|
||||
|
||||
- contractor role inside OpenClaw
|
||||
- workspace root
|
||||
- expectations for message style back to OpenClaw
|
||||
- constraints around approvals and tools
|
||||
- guidance on using session continuity instead of expecting full replay every turn
|
||||
|
||||
It should not be re-injected every turn.
|
||||
|
||||
## Storage design
|
||||
|
||||
## Static config
|
||||
|
||||
Static agent configuration belongs in OpenClaw config and is managed by the contractor CLI.
|
||||
|
||||
Examples:
|
||||
|
||||
- agent id
|
||||
- workspace
|
||||
- bridge model id
|
||||
- contractor kind
|
||||
- contractor runtime defaults
|
||||
|
||||
## Dynamic state
|
||||
|
||||
Dynamic session mapping belongs in plugin runtime state under the agent workspace.
|
||||
|
||||
Examples:
|
||||
|
||||
- OpenClaw session key to Claude session id mapping
|
||||
- session state flags
|
||||
- timestamps
|
||||
|
||||
This separation keeps declarative config and runtime state from bleeding into each other.
|
||||
|
||||
## Why not mirror full Claude state into OpenClaw session files
|
||||
|
||||
Because doing so would:
|
||||
|
||||
- create duplicated context systems
|
||||
- encourage replay-based turn handling
|
||||
- increase token cost and failure complexity
|
||||
- still fail to capture Claude's real internal runtime state perfectly
|
||||
|
||||
Instead:
|
||||
|
||||
- OpenClaw transcript remains the visible conversation record
|
||||
- Claude session remains the live cognitive state for the contractor runtime
|
||||
|
||||
## Approval and tool interaction
|
||||
|
||||
Phase 1 should keep this conservative.
|
||||
|
||||
Recommended initial stance:
|
||||
|
||||
- start with limited or no complex tool bridging beyond what is required for basic operation
|
||||
- preserve OpenClaw as the place where approvals and policy are enforced
|
||||
- design later tool bridging so Claude requests are translated into OpenClaw-hosted tool execution rather than bypassing OpenClaw directly
|
||||
|
||||
## Key risks
|
||||
|
||||
### Risk 1, poor boundary between model and runtime
|
||||
|
||||
If the bridge model tries to imitate a normal provider too literally, implementation gets awkward. It must be treated as a stateful pseudo-model.
|
||||
|
||||
### Risk 2, session mapping drift
|
||||
|
||||
If mappings are lost or stale, the user may silently lose Claude-side continuity. Recovery behavior must be explicit.
|
||||
|
||||
### Risk 3, over-forwarding context
|
||||
|
||||
If too much OpenClaw-managed prompt content is forwarded each turn, the design collapses back into dual-context management.
|
||||
|
||||
### Risk 4, under-specified reset semantics
|
||||
|
||||
Reset, new, and recovery must be clearly defined or the plugin will become unpredictable.
|
||||
|
||||
## Phase 1 implementation priorities
|
||||
|
||||
1. Register bridge model id
|
||||
2. Implement contractor metadata resolver
|
||||
3. Implement contractor CLI add flow
|
||||
4. Implement session map store
|
||||
5. Implement create/resume/send behavior in Claude ACP adapter
|
||||
6. Implement response normalization
|
||||
7. Add reset and recovery semantics
|
||||
|
||||
## References
|
||||
|
||||
### OpenClaw Claude via ACP
|
||||
|
||||
> "ACP sessions let OpenClaw run external coding harnesses (for example ... Claude Code ...) through an ACP backend plugin."
|
||||
|
||||
> "For Claude Code through ACP, the stack is:
|
||||
> 1. OpenClaw ACP session control plane
|
||||
> 2. bundled `acpx` runtime plugin
|
||||
> 3. Claude ACP adapter
|
||||
> 4. Claude-side runtime/session machinery"
|
||||
|
||||
Source:
|
||||
- https://docs.openclaw.ai/tools/acp-agents
|
||||
|
||||
### OpenClaw plugin extensibility
|
||||
|
||||
> "Plugins extend OpenClaw with new capabilities: channels, model providers, ... agent tools, or any combination."
|
||||
|
||||
Source:
|
||||
- https://docs.openclaw.ai/plugins/building-plugins
|
||||
|
||||
### Plugin entry contract
|
||||
|
||||
> "For provider plugins, tool plugins, hook plugins, and anything that is not a messaging channel."
|
||||
|
||||
Source:
|
||||
- https://docs.openclaw.ai/plugins/sdk-entrypoints
|
||||
|
||||
### Plugin CLI surface
|
||||
|
||||
> "For plugin-owned root CLI commands, prefer `api.registerCli(..., { descriptors: [...] })` ..."
|
||||
|
||||
Source:
|
||||
- https://docs.openclaw.ai/plugins/sdk-entrypoints
|
||||
Reference in New Issue
Block a user