Files
ContractorAgent/docs/claude/MODEL.md

239 lines
7.5 KiB
Markdown

# 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