Skip to content

feat: Multi-agent support with adapter pattern + Claude Code integration#2

Merged
mazzucci merged 2 commits intomainfrom
feat/multi-agent-claude-code
Mar 19, 2026
Merged

feat: Multi-agent support with adapter pattern + Claude Code integration#2
mazzucci merged 2 commits intomainfrom
feat/multi-agent-claude-code

Conversation

@mazzucci
Copy link
Copy Markdown
Owner

Summary

Refactors the monolithic flush.py into a core engine + adapter pattern to support multiple coding agents with consistent trace output in Phoenix.

What changed

File Change
hooks/core.py New agent-agnostic engine: NormalizedEvent dataclass, turn assignment, span building, Phoenix posting
hooks/adapters/cursor.py Cursor adapter: buffer I/O, atomic drain, hook event normalisation
hooks/adapters/claude_code.py Claude Code adapter: JSONL transcript parser, tool_use/result pairing, thinking blocks
hooks/flush.py New entrypoint with --agent flag dispatching to adapters
hooks/claude-code-trace-hook.sh Claude Code Stop hook script
install.sh Auto-detects Cursor + Claude Code, installs hooks for each
docker-compose.yml Exposes gRPC port 4317 for OTel collector
.github/workflows/ci.yml CI: Python 3.10-3.13 tests, lint, shellcheck
tests/test_flush.py 35 tests (was 21): core engine, both adapters, cross-adapter parity
README.md Multi-agent docs, architecture diagram, badges

Architecture

hooks/
├── flush.py                       # Entrypoint: --agent cursor|claude_code
├── core.py                        # NormalizedEvent → turns → spans → Phoenix
├── trace-hook.sh                  # Cursor hook (unchanged)
├── claude-code-trace-hook.sh      # Claude Code Stop hook
└── adapters/
    ├── __init__.py                # Adapter registry
    ├── cursor.py                  # Cursor: buffer I/O + normalisation
    └── claude_code.py             # Claude Code: transcript parser

Key design decisions

  • Both adapters produce identical span structures via NormalizedEvent → consistent Phoenix traces regardless of agent
  • Claude Code uses Stop hook + transcript parsing (not OTel native) for trace-level parity with Cursor
  • Backward compatible: CURSOR_TRACES_* env vars still work
  • Extensible: adding a new agent = one adapter file + registry entry

Tests

All 35 tests pass:

  • 20 core engine tests
  • 6 Cursor adapter tests
  • 8 Claude Code adapter tests
  • 1 cross-adapter parity test

Refactors the monolithic flush.py into a core engine + adapter pattern
to support multiple coding agents with consistent trace output.

## Architecture

- **hooks/core.py** — Agent-agnostic engine: NormalizedEvent dataclass,
  turn assignment, span building, monotonic timestamps, Phoenix posting
- **hooks/adapters/cursor.py** — Cursor adapter: buffer I/O, atomic drain,
  hook event normalisation (all 13 hook types)
- **hooks/adapters/claude_code.py** — Claude Code adapter: JSONL transcript
  parser with tool_use/tool_result pairing, thinking blocks, sub-agent support
- **hooks/flush.py** — New entrypoint: CLI with --agent flag, dispatches
  to the appropriate adapter then through the core pipeline

## New files

- hooks/claude-code-trace-hook.sh — Claude Code Stop hook script
- .github/workflows/ci.yml — CI with Python 3.10-3.13, lint, shellcheck

## Changes

- install.sh: Auto-detects Cursor (~/.cursor/) and Claude Code (~/.claude/),
  installs hooks for each, registers Stop hook in Claude settings.json
- docker-compose.yml: Exposes gRPC port 4317 for OTel collector
- tests/test_flush.py: 35 tests (was 21) covering core engine, both adapters,
  and cross-adapter span parity
- README.md: Multi-agent docs, architecture diagram, comparison table, badges

## Key design decisions

- Both adapters produce identical span structures via NormalizedEvent
- Claude Code uses Stop hook + transcript parsing (not OTel native) for
  trace-level parity with Cursor
- Backward compatible: CURSOR_TRACES_* env vars still work
- Adding a new agent = one adapter file + registry entry
- Add 'shellcheck source=/dev/null' directives for non-constant source
  in trace-hook.sh and claude-code-trace-hook.sh
- Replace sed with bash parameter expansion for timestamp injection
  in trace-hook.sh
@mazzucci mazzucci merged commit 8bbf1f7 into main Mar 19, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant