| name | heterogeneous-agent |
| description | Implement or debug LobeHub heterogeneous agents. Use for Claude Code/Codex adapters, external CLI agents, event mapping, IPC, persistence, tool-call chains, sessions, traces, or adapter bugs. |
Heterogeneous Agent Development
Use this skill when the bug or feature lives in the external CLI agent pipeline, not the normal server-side agent runtime.
Use This Skill For
- Adding or changing a driver under
apps/desktop/src/main/modules/heterogeneousAgent/drivers/
- Editing an adapter under
packages/heterogeneous-agents/src/adapters/
- Debugging
heteroAgentRawLine transport, window.__HETERO_AGENT_TRACE, or executeHeterogeneousAgent
- Fixing Claude Code stream-json bugs such as duplicate partial/full chunks, broken
message.id boundaries, missing tool_result, TodoWrite state drift, or subagent thread routing
- Fixing Codex JSONL bugs such as mixed multi-tool messages, broken turn boundaries, or missing tool-result mapping
- Fixing step-boundary, tool persistence, subagent thread, or resume bugs in Claude Code / Codex flows
- Reproducing multi-tool mixing, orphan tool messages, or stuck tool-result loading
Pipeline Map
- CLI raw stdout / JSONL
- Electron main spawns the CLI and broadcasts
heteroAgentRawLine
- Adapter maps raw provider events into
HeterogeneousAgentEvent
executeHeterogeneousAgent persists assistant/tool messages and forwards stream events
createGatewayEventHandler hydrates the UI
- Only after this path looks correct should you move on to
agent-tracing or context-engine debugging
Read These Files First
apps/desktop/src/main/controllers/HeterogeneousAgentCtr.ts
apps/desktop/src/main/modules/heterogeneousAgent/drivers/claudeCode.ts
apps/desktop/src/main/modules/heterogeneousAgent/drivers/codex.ts
packages/heterogeneous-agents/src/adapters/claudeCode.ts
packages/heterogeneous-agents/src/adapters/codex.ts
src/store/chat/slices/agentRun/actions/transports/hetero/heterogeneousAgentExecutor.ts
src/store/chat/slices/agentRun/actions/__tests__/heterogeneousAgentExecutor.test.ts
Default Debug Order
- Prove whether the raw CLI output is correct before touching UI code. The app records every real session — read the most recent one via
cat .heerogeneous-tracing/.last-live-trace rather than hand-rolling a claude -p repro (see references/debug-workflow.md §2).
- If raw output is correct, compare it with adapter output. In dev,
executeHeterogeneousAgent exposes window.__HETERO_AGENT_TRACE.
- If adapted events look correct, inspect
persistToolBatch, persistToolResult, step transitions, and subagent routing.
- Turn the repro into a focused test before fixing.
- Only after the transport/adapter/executor path looks sound should you debug later-stage message processing.
Critical Invariants
- One raw tool item must map to one stable
ToolCallPayload.id.
- A new main-agent step must emit a boundary signal before events are forwarded to the new assistant.
- In Claude Code, multiple assistant events with the same
message.id are one turn, not multiple turns.
- In Claude Code,
tool_result lives in type: 'user' events, not assistant events.
- In Claude Code partial mode,
message_delta.usage is authoritative; do not trust echoed usage on every assistant block.
persistToolBatch must pre-register assistant tools[] before creating tool messages.
- Every tool message must keep
parentId equal to the owning assistant and tool_call_id equal to the tool id.
tool_result must resolve an existing toolMsgIdByCallId.
- Subagent chunks must stay in thread scope and must not be forwarded into the main assistant stream.
- Never clear the global
toolMsgIdByCallId map at main step boundaries.
Common Bug Patterns
- Claude Code duplicates text or thinking:
check whether partial deltas and the later full assistant block are both being emitted.
- Claude Code opens too many assistant messages:
check whether the adapter is cutting steps on every assistant event instead of only on
message.id changes.
- Claude Code tool results never land:
check whether
type: 'user' tool_result blocks are being ignored because the code only inspects assistant events.
- Claude Code TodoWrite cards look stale:
check whether synthesized
pluginState.todos is being attached at tool-result time.
- Claude Code subagent transcript leaks into the main bubble:
check
parent_tool_use_id handling and whether subagent chunks are being forwarded to the main gateway handler.
- Multiple Codex tools collapse into one assistant message:
first check whether the adapter emits a usable step boundary such as
newStep or an equivalent turn-change signal.
- Orphan tool messages:
first check step-transition ordering and whether
persistToolBatch Phase 1 ran before tool message creation.
- Tool bubble stays loading:
look for
tool_result for unknown toolCallId and missing result_msg_id backfill.
- Subagent tools show up in the main bubble:
check for subagent chunks reaching the main gateway handler.
- Wrong terminal-error guide (e.g. "usage limit reached" shown for a network drop):
a classifier is branching on a structured field whose mere presence isn't its meaning.
Grep the field across all event states in a real trace before trusting it — see
references/debug-workflow.md §8 (CC
rate_limit_info rides on status: "allowed" too).
References