Skip to content

feat: add native Anthropic Messages API support via adapter pattern#19

Merged
Jiaaqiliu merged 1 commit intoaiming-lab:mainfrom
Program120:feat/anthropic-adapter
Mar 17, 2026
Merged

feat: add native Anthropic Messages API support via adapter pattern#19
Jiaaqiliu merged 1 commit intoaiming-lab:mainfrom
Program120:feat/anthropic-adapter

Conversation

@Program120
Copy link
Contributor

Summary

  • Add AnthropicAdapter — translates Anthropic Messages API to OpenAI-compatible format
  • Restore PROVIDER_PRESETS base_url fallback with new anthropic preset
  • Convert httpx exceptions to urllib errors for unified retry mechanism
  • Support json_mode via system prompt injection for Anthropic provider
  • Add httpx as optional dependency (pip install researchclaw[anthropic])
  • Add detailed changelog with architecture diagrams: docs/CHANGELOG_ANTHROPIC_ADAPTER.md

Zero Impact on Existing Providers

AnthropicAdapter is only instantiated when provider == "anthropic".
For all other providers, self._anthropic remains None — code path is identical to before.

Test Plan

  • Set ANTHROPIC_API_KEY and run python tests/test_anthropic.py
  • Verify OpenAI/OpenRouter/DeepSeek providers still work
  • Confirm no hardcoded API keys in diff

- Add AnthropicAdapter that translates Anthropic Messages API responses
  to OpenAI-compatible format, enabling seamless provider switching
- Restore PROVIDER_PRESETS base_url fallback logic with new anthropic preset
- Convert httpx exceptions to urllib errors for unified retry mechanism
- Support json_mode via system prompt injection for Anthropic provider
- Add httpx as optional dependency (pip install researchclaw[anthropic])
- Add connectivity test and detailed changelog with architecture diagrams
@Jiaaqiliu Jiaaqiliu merged commit 9c0a473 into aiming-lab:main Mar 17, 2026
Jiaaqiliu added a commit that referenced this pull request Mar 17, 2026
Merged community PRs:
- PR #12: researchclaw init command and config auto-detection
- PR #14: CONTRIBUTING.md
- PR #17: ssh_remote and colab_drive experiment sandbox backends
- PR #19: native Anthropic Messages API support via adapter pattern

Additional fixes:
- Deduplicate pyproject.toml optional-dependencies section
- Handle OSError in colab drive availability check
- Add test_outputs and local docs to .gitignore
@Jiaaqiliu
Copy link
Collaborator

Hi @Program120, thanks for this well-structured contribution!

We've reviewed and merged this PR. The Anthropic Messages API adapter is now part of main, enabling native Claude model support.

What we did during integration:

  • Resolved merge conflicts in client.py and __init__.py — our MetaClaw bridge feature was added in parallel, so we carefully merged the Anthropic adapter's if self._anthropic branching with the MetaClaw fallback logic.
  • The PROVIDER_PRESETS dict and from_rc_config() factory method are both integrated cleanly.

During our post-merge code audit, we identified a few areas for future improvement:

  1. stop_reason mapping: Anthropic returns "max_tokens" / "end_turn", but the downstream code expects OpenAI-style "length" / "stop". This means truncated detection is currently a no-op for Anthropic responses. A mapping dict would fix this.
  2. Multi-part content: The adapter only extracts the first content block (data["content"][0]). Anthropic can return multiple text blocks — concatenating all type: "text" blocks would be more robust.
  3. MetaClaw bridge interaction: When both Anthropic provider and MetaClaw bridge are enabled, the adapter receives the proxy URL instead of the Anthropic API URL. This combination should either be guarded against or handled explicitly.
  4. httpx.Client per-call: Creating a new httpx.Client on each API call loses connection pooling. Reusing a single client instance in __init__ would improve performance.

None of these are blockers — the adapter works correctly for the standard use case (direct Anthropic API). Would love to see follow-up PRs addressing any of these!

Excellent adapter pattern and great documentation in the changelog. Thanks for contributing!

Jiaaqiliu added a commit that referenced this pull request Mar 17, 2026
PR #12 (cli init):
- Fix provider replacement: match "openai-compatible" instead of "openai"
- Fix example config path: search repo root + package dir, not just CWD
- Handle EOFError on stdin close during interactive prompt
- Return exit code 1 when refusing to overwrite existing config

PR #17 (SSH/Colab sandbox):
- Fix shell injection: shlex.quote() all user-supplied values in commands
- Fix SSH option ordering: ConnectTimeout placed before hostname
- Fix subdirectory support: run_project() and scp_upload() now copy dirs
- Fix Docker cmd: add explicit python3 invocation, fix GPU flag quoting
- Add cleanup of remote dir on upload failure

PR #19 (Anthropic adapter):
- Fix stop_reason mapping: end_turn→stop, max_tokens→length (truncation)
- Fix MetaClaw conflict: adapter uses original URL, not proxy URL
- Extract all text content blocks, not just the first
- Concatenate multiple system messages instead of dropping earlier ones
- Catch all httpx transport errors (ReadError, RemoteProtocolError, etc.)
- Detect Anthropic error responses before conversion

config.py:
- Remove 84 lines of duplicate function definitions (dead code)
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.

2 participants