Skip to content

Commit f25c1b5

Browse files
Merge pull request #166 from Annotation-Garden/develop
Release 0.7.11: Claude Platform on AWS, usage and cache reporting, extended thinking
2 parents cc8de28 + 162c87f commit f25c1b5

85 files changed

Lines changed: 6644 additions & 4766 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.context/agent-architecture.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ HEDit uses a LangGraph-based multi-agent workflow to convert natural language ev
6868

6969
### 6. VisionAgent (`src/agents/vision_agent.py`)
7070
- **Input**: Base64-encoded image
71-
- **Process**: Uses vision-language models (e.g., Qwen-VL via OpenRouter)
71+
- **Process**: Uses a Claude model (natively multimodal; no separate vision vendor)
7272
- **Output**: Natural language description of image content
7373
- **Key feature**: Enables image-to-HED annotation pipeline
7474

@@ -100,7 +100,12 @@ Defined in `src/agents/state.py` as `HedAnnotationState(TypedDict)`:
100100

101101
## Configuration
102102

103-
- **LLM Provider**: OpenRouter API (production), with Ollama fallback
103+
- **LLM Provider**: Anthropic Claude via the Claude Platform on AWS (Anthropic-operated
104+
Messages API, AWS Marketplace billing; not Amazon Bedrock)
105+
- **Offered models**: `claude-haiku-4-5` (default) and `claude-sonnet-5`
104106
- **Default model**: Configurable via environment/headers
105-
- **BYOK support**: Users can provide their own API keys
107+
- **BYOK support**: Users can provide their own Anthropic key (`X-Anthropic-Key`),
108+
which routes to api.anthropic.com
109+
- **Prompt caching**: The annotation system prompt is cached; usage and savings are
110+
reported per request (see `docs/prompt-caching.md`)
106111
- **Streaming**: LangGraph `astream_events` for real-time progress via SSE

.context/api-and-deployment.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,23 @@
1111
- `POST /feedback`: User feedback submission
1212
- `GET /health`: Service health check
1313
- `GET /version`: Version information
14+
- `GET /metrics`: Token use, cost, and prompt-cache savings since startup
15+
(server API key required; BYOK callers get 403)
1416

1517
### Authentication Modes
16-
1. **Server mode**: `X-API-Key` header (server's OpenRouter key)
17-
2. **BYOK mode**: `X-OpenRouter-Key` header (user's own API key)
18+
1. **Server mode**: `X-API-Key` header (server's Anthropic credentials are used)
19+
2. **BYOK mode**: `X-Anthropic-Key` header (user's own Anthropic key, `sk-ant-...`,
20+
routed to api.anthropic.com)
1821
3. **Public endpoints**: `/feedback`, `/health`, `/version`
1922

2023
### Model Override Headers
21-
- `X-OpenRouter-Model`: Override annotation model
22-
- `X-OpenRouter-Vision-Model`: Override vision model
23-
- `X-OpenRouter-Provider`: Override provider routing
24-
- `X-OpenRouter-Temperature`: Override temperature
24+
- `X-Anthropic-Model`: Override annotation model
25+
- `X-Anthropic-Eval-Model`: Override evaluation model
26+
- `X-Anthropic-Vision-Model`: Override vision model
27+
- `X-Anthropic-Temperature`: Override temperature
28+
29+
The legacy `X-OpenRouter-*` spellings of these names (plus `X-OpenRouter-Key`) are
30+
still accepted as transport; provider-routing headers are ignored.
2531

2632
### CORS
2733
- Production: `hedit.pages.dev`, `annotation.garden`

.env.example

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ API_KEYS=your-generated-api-key-here
1919
REQUIRE_API_AUTH=true
2020

2121
# BYOK (Bring Your Own Key) Mode
22-
# When enabled, users can provide their own OpenRouter API key via X-OpenRouter-Key header
23-
# Their key is used for LLM calls (billing goes to their account)
22+
# When enabled, users can provide their own Anthropic API key (sk-ant-...)
23+
# via the X-Anthropic-Key header. Their key is used for LLM calls against
24+
# the first-party Anthropic API (billing goes to their account).
2425
# Set to "false" to require server API keys only
2526
ALLOW_BYOK=true
2627

@@ -40,58 +41,63 @@ ALLOW_LOCALHOST_CORS=true
4041
# LLM Provider Configuration
4142
# ============================================================================
4243

43-
# Provider: "openrouter" (recommended) or "ollama" (local GPU)
44-
LLM_PROVIDER=openrouter
45-
4644
# Temperature: 0.0-1.0, lower = more consistent
4745
LLM_TEMPERATURE=0.1
4846

4947
# ============================================================================
50-
# OpenRouter Configuration (when LLM_PROVIDER=openrouter)
48+
# Anthropic Configuration (Claude Platform on AWS)
5149
# ============================================================================
52-
53-
# Get your API key from https://openrouter.ai/
54-
OPENROUTER_API_KEY=your-openrouter-api-key-here
55-
56-
# Test API key (separate key to track testing costs)
57-
# Used only by integration tests that make real LLM calls
58-
# OPENROUTER_API_KEY_FOR_TESTING=your-testing-api-key-here
50+
# LLM calls go to Claude via the Claude Platform on AWS (Anthropic-operated
51+
# Messages API, AWS Marketplace billing; NOT Amazon Bedrock).
52+
# All three values are required in server mode; the endpoint rejects
53+
# requests without the anthropic-workspace-id header.
54+
# Key: AWS Console -> Claude Platform on AWS -> API keys -> Generate a key
55+
# Workspace: AWS Console -> Claude Platform on AWS -> Workspaces (wrkspc_...)
56+
ANTHROPIC_API_KEY=your-claude-platform-key-here
57+
ANTHROPIC_BASE_URL=https://aws-external-anthropic.us-east-2.api.aws
58+
ANTHROPIC_WORKSPACE_ID=wrkspc_your_workspace_id
5959

6060
# ============================================================================
6161
# Model Configuration
6262
# ============================================================================
63-
# Each agent type has its own model and provider for optimal performance.
63+
# Offered models: claude-haiku-4-5 (default) and claude-sonnet-5.
6464

65-
# Annotation Model (Claude Haiku 4.5 via Anthropic - high quality with prompt caching)
66-
ANNOTATION_MODEL=anthropic/claude-haiku-4.5
67-
ANNOTATION_PROVIDER=anthropic
65+
# Annotation Model (Claude Haiku 4.5 - fast, near-frontier quality)
66+
ANNOTATION_MODEL=claude-haiku-4-5
6867

69-
# Evaluation/Assessment Model (Qwen3.5-122B via Alibaba - fast and cost-effective)
70-
# Used for evaluation, assessment, and feedback agents
71-
EVALUATION_MODEL=qwen/qwen3.5-122b-a10b
72-
EVALUATION_PROVIDER=alibaba
68+
# Evaluation/Assessment Model (the judge stays on Haiku)
69+
EVALUATION_MODEL=claude-haiku-4-5
7370

74-
# Vision Model (Qwen3.5-122B via Alibaba - accepts vision, fast)
75-
VISION_MODEL=qwen/qwen3.5-122b-a10b
76-
VISION_PROVIDER=alibaba
71+
# Vision Model (Claude models are natively multimodal)
72+
VISION_MODEL=claude-haiku-4-5
73+
74+
# Sonnet 5 is available for comparison. It matched Haiku 4.5 (which runs with
75+
# extended thinking) on first-attempt validity at 2.3x the cost, so it is not
76+
# recommended as a default; see docs/reasoning.md.
77+
# ANNOTATION_MODEL=claude-sonnet-5
7778

7879
# ============================================================================
79-
# Alternative Models
80+
# Prompt Cache Lifetime
8081
# ============================================================================
81-
# For highest quality (but slower and more expensive):
82-
# ANNOTATION_MODEL=openai/gpt-5.2
83-
# ANNOTATION_PROVIDER=
84-
85-
# For fastest results:
86-
# ANNOTATION_MODEL=anthropic/claude-haiku-4.5
87-
# ANNOTATION_PROVIDER=
82+
# The annotation system prompt (~21.8k tokens of HED vocabulary guide) is
83+
# cached, which cuts input cost by ~90% on a cache hit. Entries live 5
84+
# minutes by default, which suits server traffic; a cache write costs 1.25x,
85+
# so break-even is the second request inside the window.
86+
# Set to 1h for interactive use where requests are minutes apart (a 1-hour
87+
# write costs 2x and pays off from the third request in the hour).
88+
# See docs/prompt-caching.md
89+
# HEDIT_PROMPT_CACHE_TTL=5m
8890

8991
# ============================================================================
90-
# Ollama Configuration (when LLM_PROVIDER=ollama)
92+
# Annotation Reasoning Budget
9193
# ============================================================================
92-
# Only used if LLM_PROVIDER=ollama (local GPU deployment)
93-
# LLM_BASE_URL=http://localhost:11435
94-
# LLM_MODEL=qwen2.5:32b
94+
# The annotation agent runs with extended thinking, which took first-attempt
95+
# validity from 5/15 to 13/15 on the benchmark descriptions, cut total LLM
96+
# calls by a third, and cost 24% more per request with roughly twice the
97+
# latency. Raise the budget, or set 0/off to disable it for a
98+
# latency-sensitive deployment. Ignored on Sonnet 5, which chooses its own
99+
# depth (adaptive). See docs/reasoning.md
100+
# HEDIT_ANNOTATION_THINKING_BUDGET=2048
95101

96102
# ============================================================================
97103
# HED Configuration
@@ -169,6 +175,4 @@ LOG_LEVEL=INFO
169175
# GITHUB_REPOSITORY_OWNER=Annotation-Garden
170176
# GITHUB_REPOSITORY=hedit
171177

172-
# Feedback processing uses OPENROUTER_API_KEY_FOR_TESTING (if set) to track
173-
# feedback-related LLM costs separately from annotation costs.
174-
# Falls back to OPENROUTER_API_KEY if testing key is not set.
178+
# Feedback processing uses the ANTHROPIC_API_KEY server credentials.

.github/workflows/docker-build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ jobs:
3333
docker run -d --name hed-bot-test \
3434
-p 38427:38427 \
3535
-e REQUIRE_API_AUTH=false \
36-
-e LLM_PROVIDER=openrouter \
37-
-e OPENROUTER_API_KEY=test-key-for-ci \
36+
-e LLM_PROVIDER=anthropic \
37+
-e ANTHROPIC_API_KEY=test-key-for-ci \
3838
-e LLM_TEMPERATURE=0.1 \
3939
hed-bot-test:ci
4040

.github/workflows/process-feedback.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ jobs:
6868
if: steps.feedback.outputs.has_files == 'true'
6969
env:
7070
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
71-
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY_FOR_TESTING }}
71+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
72+
ANTHROPIC_BASE_URL: ${{ vars.ANTHROPIC_BASE_URL }}
73+
ANTHROPIC_WORKSPACE_ID: ${{ vars.ANTHROPIC_WORKSPACE_ID }}
7274
DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }}
7375
run: |
7476
# Process each feedback file

.github/workflows/release.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ jobs:
5656
body: |
5757
## HEDit ${{ steps.get_version.outputs.VERSION }}
5858
59+
Release notes in prose: [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md)
60+
5961
${{ steps.changelog.outputs.CHANGELOG }}
6062
6163
---
@@ -82,7 +84,7 @@ jobs:
8284
8385
### Quick Start
8486
```bash
85-
# Initialize with your OpenRouter API key
87+
# Initialize the CLI (optionally with a BYOK Anthropic key)
8688
hedit init --api-key YOUR_KEY
8789
8890
# Generate HED annotation

.github/workflows/test.yml

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,10 @@ jobs:
117117
# - Integration test files (test_integration*.py, test_standalone*.py)
118118
# - Agent code (workflow, annotation, evaluation, keyword extraction, etc.)
119119
# - Validation code
120-
# - OpenRouter/LiteLLM utility
120+
# - Anthropic LLM utility
121121
# - CLI code (for CLI integration tests)
122122
# - Semantic search code
123-
INTEGRATION_PATTERNS="tests/test_.*integration|tests/test_standalone|src/agents/|src/validation/|src/utils/openrouter|src/utils/litellm|src/utils/semantic|src/cli/"
123+
INTEGRATION_PATTERNS="tests/test_.*integration|tests/test_standalone|src/agents/|src/validation/|src/utils/anthropic|src/utils/semantic|src/cli/"
124124
125125
if echo "$CHANGED" | grep -qE "$INTEGRATION_PATTERNS"; then
126126
echo "integration_needed=true" >> $GITHUB_OUTPUT
@@ -160,13 +160,15 @@ jobs:
160160
161161
- name: Run standalone tests only
162162
env:
163-
OPENROUTER_API_KEY_FOR_TESTING: ${{ secrets.OPENROUTER_API_KEY_FOR_TESTING }}
163+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
164+
ANTHROPIC_BASE_URL: ${{ vars.ANTHROPIC_BASE_URL }}
165+
ANTHROPIC_WORKSPACE_ID: ${{ vars.ANTHROPIC_WORKSPACE_ID }}
164166
run: |
165-
if [ -n "$OPENROUTER_API_KEY_FOR_TESTING" ]; then
167+
if [ -n "$ANTHROPIC_API_KEY" ]; then
166168
echo "Running standalone tests..."
167169
pytest tests/ -v -m standalone --timeout=180 --cov=src --cov-report=xml:coverage-standalone.xml --cov-report=term-missing
168170
else
169-
echo "OPENROUTER_API_KEY_FOR_TESTING not set, skipping standalone tests"
171+
echo "ANTHROPIC_API_KEY not set, skipping standalone tests"
170172
fi
171173
172174
- name: Upload standalone coverage to Codecov
@@ -185,7 +187,7 @@ jobs:
185187
needs: [check-changes]
186188
# Only run integration tests when:
187189
# 1. Push event (after merge) or manual trigger, not on PRs
188-
# 2. Integration-related files changed (agents, validation, openrouter, or test file itself)
190+
# 2. Integration-related files changed (agents, validation, anthropic, or test file itself)
189191
if: |
190192
(github.event_name == 'push' || github.event_name == 'workflow_dispatch') &&
191193
(needs.check-changes.outputs.integration_needed == 'true' || github.event_name == 'workflow_dispatch')
@@ -208,14 +210,16 @@ jobs:
208210
209211
- name: Run integration tests only
210212
env:
211-
OPENROUTER_API_KEY_FOR_TESTING: ${{ secrets.OPENROUTER_API_KEY_FOR_TESTING }}
213+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
214+
ANTHROPIC_BASE_URL: ${{ vars.ANTHROPIC_BASE_URL }}
215+
ANTHROPIC_WORKSPACE_ID: ${{ vars.ANTHROPIC_WORKSPACE_ID }}
212216
run: |
213217
# Only run if the secret is available
214-
if [ -n "$OPENROUTER_API_KEY_FOR_TESTING" ]; then
215-
echo "Running integration tests with OpenRouter..."
218+
if [ -n "$ANTHROPIC_API_KEY" ]; then
219+
echo "Running integration tests with Claude (Claude Platform on AWS)..."
216220
pytest tests/ -v -m integration --timeout=180 --cov=src --cov-report=xml:coverage-integration.xml --cov-report=term-missing
217221
else
218-
echo "OPENROUTER_API_KEY_FOR_TESTING not set, skipping integration tests"
222+
echo "ANTHROPIC_API_KEY not set, skipping integration tests"
219223
fi
220224
221225
- name: Upload integration coverage to Codecov

.rules/testing.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ Never use mocks, stubs, or fake datasets. If real testing is not possible, don't
1414

1515
## When to Write Tests
1616
- **DO:** Test with real data and actual dependencies
17-
- **DO:** Use test API keys (`OPENROUTER_API_KEY_FOR_TESTING`)
17+
- **DO:** Use the Anthropic test credentials (`ANTHROPIC_API_KEY`, with
18+
`ANTHROPIC_BASE_URL` and `ANTHROPIC_WORKSPACE_ID` for the Claude Platform on AWS)
1819
- **DO:** Test against actual file systems and real HED schemas
1920
- **DON'T:** Write tests if only mocks would work
2021
- **DON'T:** Create artificial test scenarios

.serena/memories/codebase_structure.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ hedit/
2222
│ │ ├── json_schema_loader.py # JSON schema + vocabulary extraction
2323
│ │ ├── schema_loader.py # Legacy Python schema loader
2424
│ │ ├── error_remediation.py # Error augmentation for LLM feedback
25-
│ │ ├── openrouter_llm.py # OpenRouter API integration
25+
│ │ ├── anthropic_llm.py # Anthropic Claude integration (prompt caching)
26+
│ │ ├── llm_usage.py # Token, cost, and cache accounting
2627
│ │ ├── litellm_llm.py # Alternative LLM providers
2728
│ │ ├── image_processing.py # Base64 image encoding
2829
│ │ └── github_client.py # GitHub API for feedback issues

.serena/memories/project_overview.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ HEDit is a multi-agent system for converting natural language event descriptions
77
- **Language**: Python 3.12+
88
- **Package Manager**: uv
99
- **Agent Framework**: LangGraph
10-
- **LLM Provider**: OpenRouter API (production), Ollama (fallback)
10+
- **LLM Provider**: Anthropic Claude via the Claude Platform on AWS (claude-haiku-4-5 default, claude-sonnet-5 optional)
1111
- **Validation**: HED JavaScript validator + HED Python tools (hedtools)
1212
- **Backend**: FastAPI
1313
- **CLI**: Typer + Rich

0 commit comments

Comments
 (0)