Anthropic integration
Same two paths as OpenAI: a drop-in client wrapper for TypeScript, and the language-agnostic gateway proxy.
SDK wrapper (TypeScript)
import Anthropic from "@anthropic-ai/sdk";
import { AuditTrailClient, wrapAnthropic } from "@audittrail/sdk";
const audit = new AuditTrailClient({
baseUrl: "https://your-audittrail-host",
apiKey: process.env.AUDITTRAIL_API_KEY,
});
const anthropic = wrapAnthropic(new Anthropic(), audit);
const msg = await anthropic.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: "hello" }],
});The wrapper proxies messages.create, maps Anthropic's
input_tokens/output_tokens usage onto the AuditTrail span schema, and
is structurally typed — the SDK has no runtime dependency on
@anthropic-ai/sdk. Spans join the active trace context, so wrapping
your handler in traceable() nests them properly.
SDK wrapper (Go & Rust)
Go installs an http.RoundTripper on the official anthropic-sdk-go
client; Rust wraps any Serialize request/response pair. Both map
input_tokens/output_tokens and emit one span per messages call.
audit, _ := audittrail.New(audittrail.Config{APIKey: apiKey})
client := anthropic.NewClient(
option.WithHTTPClient(audittrail.AnthropicHTTPClient(audit)),
)let response: serde_json::Value = audit
.wrap_anthropic(&request, || async { /* call anthropic */ Ok::<_, MyErr>(resp) })
.await?;See the SDK parity matrix for the full language grid.
Gateway proxy (any language)
The gateway speaks the OpenAI-compatible /chat/completions envelope and
routes by model name — claude-* (and anthropic/*) models forward to
the Anthropic API using the upstream key configured on the server
(AUDITTRAIL_GATEWAY_ANTHROPIC_KEY, or a per-request stored secret via
the X-AuditTrail-Secret header):
export OPENAI_BASE_URL="https://your-audittrail-host/api/v1/gateway/proxy/v1"
export OPENAI_API_KEY="at-gw-..." # AuditTrail virtual keyfrom openai import OpenAI
client = OpenAI()
resp = client.chat.completions.create(
model="claude-sonnet-4-5", # routed to Anthropic by the gateway
messages=[{"role": "user", "content": "hello"}],
)Every proxied call becomes a fully-attributed span with constitutional
rules evaluated server-side. Configure the upstream Anthropic key via
the AUDITTRAIL_GATEWAY_ANTHROPIC_KEY env var
(Gateway proxy) or a stored
agent secret; envelope and error semantics live in
Gateway proxy. (BYOK keys back the Operations
Assistant only — the gateway never reads them.)
Gotchas
- Anthropic requires
max_tokensonmessages.create— the wrapper passes your params through untouched, so the usual client-side validation still applies. - Through the gateway you use the OpenAI message shape even for Claude models (the gateway translates); through the wrapper you use Anthropic's native shape.
- A
claude-*request with no Anthropic key configured server-side is rejected with400 unsupported_model— the gateway never fabricates a response when a real key is expected.