docs: expand Claude contractor design
This commit is contained in:
238
docs/claude/MODEL.md
Normal file
238
docs/claude/MODEL.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# Claude Bridge Model Design
|
||||
|
||||
## Purpose
|
||||
|
||||
Define how Claude-backed contractor agents integrate into OpenClaw using a custom model seam.
|
||||
|
||||
This document is specific to the Claude phase of ContractorAgent.
|
||||
|
||||
## Why this must be a custom model
|
||||
|
||||
OpenClaw expects every agent to have a primary model. For contractor-backed agents, the actual reasoning engine is not a normal OpenClaw LLM provider call, but a Claude Code session managed outside the usual stateless completion flow.
|
||||
|
||||
Therefore the contractor integration should present itself to OpenClaw as a custom model id, while internally acting as a stateful bridge to Claude Code.
|
||||
|
||||
Recommended model id for phase 1:
|
||||
|
||||
- `contractor-claude-bridge`
|
||||
|
||||
## Mental model
|
||||
|
||||
From OpenClaw's perspective:
|
||||
|
||||
- the agent has a normal primary model
|
||||
- a model request is issued for each turn
|
||||
- the model returns assistant output
|
||||
|
||||
From the plugin's perspective:
|
||||
|
||||
- the model request is actually a routing event
|
||||
- the request identifies the OpenClaw session and agent
|
||||
- the plugin resolves a mapped Claude Code session
|
||||
- the plugin forwards only the newest actionable turn to Claude Code
|
||||
- the plugin returns Claude's output as the model response
|
||||
|
||||
So this is a pseudo-model backend with sessionful behavior.
|
||||
|
||||
## Responsibilities of the bridge model
|
||||
|
||||
The bridge model should:
|
||||
|
||||
1. accept model requests for contractor-backed agents
|
||||
2. identify the current OpenClaw session and contractor agent id
|
||||
3. resolve or create the mapped Claude Code session
|
||||
4. filter OpenClaw-managed envelope/context
|
||||
5. forward only the latest actionable message plus minimal metadata
|
||||
6. collect Claude Code output
|
||||
7. normalize that output into an OpenClaw model response
|
||||
8. persist session mapping metadata
|
||||
|
||||
The bridge model should not:
|
||||
|
||||
- act like a generic stateless LLM provider
|
||||
- replay full OpenClaw session history every turn unless recovery is required
|
||||
- try to mirror all Claude internal state into OpenClaw session files
|
||||
|
||||
## Model lifecycle
|
||||
|
||||
### First turn in an OpenClaw session
|
||||
|
||||
1. OpenClaw selects `contractor-claude-bridge` as the agent's primary model
|
||||
2. bridge model receives the turn input
|
||||
3. plugin extracts:
|
||||
- agent id
|
||||
- OpenClaw session key
|
||||
- workspace
|
||||
- latest user message
|
||||
4. no session mapping exists yet
|
||||
5. plugin creates a Claude Code session through ACP/runtime integration
|
||||
6. plugin injects initial contractor instructions and minimal OpenClaw metadata
|
||||
7. plugin sends the latest user message
|
||||
8. Claude responds
|
||||
9. plugin stores the new mapping and returns assistant output to OpenClaw
|
||||
|
||||
### Later turns
|
||||
|
||||
1. bridge model receives next turn
|
||||
2. plugin resolves existing mapping
|
||||
3. plugin resumes or continues the Claude Code session
|
||||
4. plugin forwards latest user message only
|
||||
5. Claude responds
|
||||
6. plugin returns normalized response and updates mapping timestamps
|
||||
|
||||
### Reset or new session
|
||||
|
||||
Reset semantics should be explicit.
|
||||
|
||||
Recommended behavior:
|
||||
|
||||
- OpenClaw `/new` or reset-equivalent for this agent should create a fresh Claude session transcript
|
||||
- keep the OpenClaw agent identity and routing stable
|
||||
- replace the existing mapping for the OpenClaw session key
|
||||
- reinject initial contractor instructions
|
||||
|
||||
## Session mapping contract
|
||||
|
||||
Bridge model depends on a persistent mapping store.
|
||||
|
||||
Suggested record shape:
|
||||
|
||||
```ts
|
||||
type ContractorSessionMapEntry = {
|
||||
openclawSessionKey: string
|
||||
agentId: string
|
||||
contractor: "claude"
|
||||
claudeSessionId: string
|
||||
workspace: string
|
||||
createdAt: string
|
||||
lastActivityAt: string
|
||||
state: "active" | "closed" | "orphaned"
|
||||
}
|
||||
```
|
||||
|
||||
## Input filtering
|
||||
|
||||
The bridge model must not blindly forward the entire model input payload to Claude Code.
|
||||
|
||||
Instead it should derive a contractor payload with:
|
||||
|
||||
- latest user-visible message
|
||||
- minimal agent metadata
|
||||
- minimal workspace metadata
|
||||
- optional turn metadata needed for reply formatting or approvals
|
||||
|
||||
It should ignore or strip:
|
||||
|
||||
- repeated long-form system envelope generated by OpenClaw
|
||||
- redundant chat history already owned by Claude session memory
|
||||
- internal bookkeeping not useful to Claude Code
|
||||
|
||||
This keeps Claude as the owner of live context.
|
||||
|
||||
## Initial contractor instructions
|
||||
|
||||
When creating a fresh Claude session, inject a stable bootstrap payload that includes:
|
||||
|
||||
- identity of the contractor role inside OpenClaw
|
||||
- workspace path
|
||||
- allowed interaction style with OpenClaw
|
||||
- tool/skill access strategy
|
||||
- output expectations for OpenClaw replies
|
||||
- rule that session continuity lives primarily in Claude Code session state
|
||||
|
||||
This injection should happen on session creation and hard resets, not every turn.
|
||||
|
||||
## Output normalization
|
||||
|
||||
Claude output must be normalized before returning to OpenClaw.
|
||||
|
||||
Normalization should handle:
|
||||
|
||||
- plain assistant text
|
||||
- tool-use related status text
|
||||
- multi-part responses if Claude adapter streams or chunks
|
||||
- failures or blocked actions
|
||||
- explicit clarification requests
|
||||
|
||||
The custom model should emit output in a way OpenClaw can treat as a normal assistant response.
|
||||
|
||||
## Session file interaction
|
||||
|
||||
The current working assumption is:
|
||||
|
||||
- OpenClaw session files remain the system of record for visible conversation state
|
||||
- Claude session state remains the system of record for internal live reasoning context
|
||||
|
||||
Therefore the bridge model should inject Claude responses back into OpenClaw's normal session response path, rather than bypassing it.
|
||||
|
||||
This means the plugin should preserve OpenClaw's normal transcript behavior while avoiding full upstream context replay.
|
||||
|
||||
## Recovery behavior
|
||||
|
||||
### Missing Claude session
|
||||
|
||||
If the mapped Claude session is missing or invalid:
|
||||
|
||||
1. mark mapping as `orphaned`
|
||||
2. create a fresh Claude session
|
||||
3. inject bootstrap context
|
||||
4. optionally summarize minimal recent OpenClaw-visible context for recovery
|
||||
5. store replacement mapping
|
||||
|
||||
This should be treated as degraded recovery, not the normal path.
|
||||
|
||||
### Mapping corruption
|
||||
|
||||
If mapping storage cannot be read:
|
||||
|
||||
- fail closed for the turn if data integrity is uncertain
|
||||
- or create a new Claude session only when policy allows and user impact is acceptable
|
||||
|
||||
## Why not use a normal provider model directly
|
||||
|
||||
Because a normal provider model implies:
|
||||
|
||||
- stateless prompt in
|
||||
- stateless completion out
|
||||
- OpenClaw-owned context reconstruction each turn
|
||||
|
||||
That is the opposite of the intended contractor design.
|
||||
|
||||
The custom model seam is useful precisely because it lets OpenClaw keep the agent abstraction while delegating real session continuity to Claude Code.
|
||||
|
||||
## Open questions
|
||||
|
||||
1. Which provider/plugin registration seam is best for the bridge model id?
|
||||
2. What exact request shape does the plugin receive for a model turn in OpenClaw runtime?
|
||||
3. Where should bootstrap instructions be stored, generated text, template file, or config?
|
||||
4. How should streaming behavior be represented if Claude session output arrives incrementally?
|
||||
5. How should tool requests from Claude be surfaced back into OpenClaw tool execution?
|
||||
|
||||
## References
|
||||
|
||||
### OpenClaw plugin capability
|
||||
|
||||
> "Plugins extend OpenClaw with new capabilities: channels, model providers, ... agent tools, or any combination."
|
||||
|
||||
Source:
|
||||
- https://docs.openclaw.ai/plugins/building-plugins
|
||||
|
||||
### Plugin entry model
|
||||
|
||||
> "For provider plugins, tool plugins, hook plugins, and anything that is not a messaging channel."
|
||||
|
||||
Source:
|
||||
- https://docs.openclaw.ai/plugins/sdk-entrypoints
|
||||
|
||||
### Claude Code 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
|
||||
Reference in New Issue
Block a user