Build: The Anthropic Client
Maps to: Task 8. Kind: Build.
Objective
Implement AnthropicClient — a concrete ModelClient that builds the request, sends it, and parses the completion into a ModelResponse. Test it entirely against a wiremock mock server, spending no API credits.
Scaffold
Create: crates/panoptes-harness/src/anthropic.rs. Modify: crates/panoptes-harness/src/lib.rs (re-export AnthropicClient).
Dependencies: no manifest changes — reqwest and the dev-only wiremock were declared when you created the crate. The test needs #[tokio::test], which tokio's full features already cover.
Expected result: cargo test -p panoptes-harness anthropic → 1 test passes (parses_a_mocked_completion).
The spec (givens)
AnthropicClientfields:api_key,model,base_url(all publicString—base_urlinjectable so tests can point at the mock) plus a privatehttp: reqwest::Client. Constructornew(api_key, model, base_url).- Request:
POST {base_url}/v1/messageswith headersx-api-key: <key>andanthropic-version: 2023-06-01; JSON body{"model": …, "max_tokens": 1024, "messages": [{"role": "user", "content": <prompt>}]}. - Response shape to deserialize:
{"content": [{"text": …}, …], "usage": {"input_tokens": …, "output_tokens": …}}— concatenate the block texts in order.
Full code: Answer Key, Task 8.
Concepts exercised
reqwestJSON POST with headers.- Deserializing a nested API response into typed structs.
wiremockmock definitions and#[tokio::test].
The build loop (you drive)
- Write the failing test
parses_a_mocked_completion: mount a mock returning a known completion + usage, callgenerate, assert the parsed text and token counts. - Predict: the response JSON has a
contentarray of blocks. What does your parsing do if the array is empty? Decide the behavior before implementing. - Run, check.
- Implement the client with an injectable
base_url. - Run green, commit.
Done when
cargo test -p panoptes-harness anthropic passes. Adding a second provider (OpenAI, a local gateway) is now "copy this file, change the request/response shapes" — the trait makes providers uniform.