spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

Add implementation specification for ANT_ONLY_METADATA_USER_ID featureBrowse files
This spec documents how to implement the ANT_ONLY_METADATA_USER_ID
environment variable feature that allows internal Anthropic jobs
(Oracle, Oncall, Ambient, etc.) to pass custom metadata through
Claude Code sessions to the API for usage tracking and incident triage.

Key points:
- Read ANT_ONLY_METADATA_USER_ID env var
- Pass value as metadata.user_id in API requests
- Use tree shaking to restrict to internal builds only
- Expected format: {"user": "<username>", "job": "<job_name>"}
Claude authored on Dec 11, 2025 parent 6358669 · commit 3a1c529e231a
1 changed file+221 -0compared with 6358669
AANT_ONLY_METADATA_USER_ID_SPEC.md
@@ -1,0 +1,221 @@
1+# ANT_ONLY_METADATA_USER_ID Implementation Specification
2+
3+## Overview
4+
5+This document specifies the implementation of the `ANT_ONLY_METADATA_USER_ID` environment variable feature for Claude Code. This feature allows internal Anthropic jobs (like Claude Oracle, Oncall, Ambient, etc.) to pass custom metadata through Claude Code sessions to the Anthropic API for tracking, rate limiting, and incident triage purposes.
6+
7+## Background
8+
9+From the Slack discussion:
10+- Internal API jobs launched via Claude Code currently lack user metadata showing `job_id` or `username` in `api_usage`
11+- ~85% of requests from heavy CC users (like Closing The Loop org) have no user_metadata or job identifier
12+- This metadata is critical for:
13+ - Managing Internal API rate limits
14+ - Triaging incidents
15+ - Setting up alerting that pings the DRI researchers
16+ - Understanding which jobs are driving token usage
17+
18+## Requirements
19+
20+1. **Environment Variable**: Claude Code must read an environment variable called `ANT_ONLY_METADATA_USER_ID`
21+2. **API Integration**: The value must be passed to all Anthropic Messages API calls in the `metadata.user_id` field
22+3. **Tree Shaking**: Only Anthropic internal builds should be able to use this feature
23+4. **Format**: The expected format is a JSON object: `{"user": "<anthropic_username>", "job": "<job_name>"}`
24+ - Example: `{"user": "tedm", "job": "tedm-1208-mu-g-18x"}`
25+ - Or: `{"user": "vinke", "job": "claude-oracle:fluorine:vinke"}`
26+
27+## Implementation
28+
29+### 1. Environment Variable Reading
30+
31+In the appropriate configuration/env module (likely `src/config/env.ts` or similar):
32+
33+```typescript
34+// Environment variable for Anthropic internal builds only
35+// This is used to pass job metadata to the API for usage tracking
36+export function getAntOnlyMetadataUserId(): string | undefined {
37+ // Only available in Anthropic internal builds
38+ if (!isAnthropicBuild()) {
39+ return undefined;
40+ }
41+ return process.env.ANT_ONLY_METADATA_USER_ID;
42+}
43+```
44+
45+### 2. API Request Metadata
46+
47+When constructing API requests to the Anthropic Messages API, add the metadata:
48+
49+```typescript
50+// In the API client module (e.g., src/api/anthropic.ts)
51+import { getAntOnlyMetadataUserId } from '../config/env';
52+
53+function buildApiRequestMetadata(): Record<string, string> | undefined {
54+ const metadataUserId = getAntOnlyMetadataUserId();
55+
56+ if (!metadataUserId) {
57+ return undefined;
58+ }
59+
60+ return {
61+ user_id: metadataUserId
62+ };
63+}
64+
65+// When creating a message:
66+const response = await client.messages.create({
67+ model: selectedModel,
68+ max_tokens: maxTokens,
69+ messages: conversationMessages,
70+ // ... other parameters
71+ metadata: buildApiRequestMetadata()
72+});
73+```
74+
75+### 3. Tree Shaking for Internal Builds
76+
77+The feature should be conditionally compiled out for public builds using build-time flags:
78+
79+```typescript
80+// Using a build-time constant
81+declare const __ANT_INTERNAL_BUILD__: boolean;
82+
83+export function isAnthropicBuild(): boolean {
84+ // This will be replaced at build time
85+ // For internal builds: true
86+ // For public builds: false (and the code will be tree-shaken)
87+ if (typeof __ANT_INTERNAL_BUILD__ !== 'undefined') {
88+ return __ANT_INTERNAL_BUILD__;
89+ }
90+ return false;
91+}
92+```
93+
94+In the build configuration (esbuild/webpack/rollup):
95+
96+```javascript
97+// For public builds:
98+define: {
99+ '__ANT_INTERNAL_BUILD__': 'false'
100+}
101+
102+// For internal builds:
103+define: {
104+ '__ANT_INTERNAL_BUILD__': 'true'
105+}
106+```
107+
108+### 4. Validation (Optional but Recommended)
109+
110+```typescript
111+function validateMetadataUserId(value: string): boolean {
112+ try {
113+ const parsed = JSON.parse(value);
114+ return typeof parsed.user === 'string' && typeof parsed.job === 'string';
115+ } catch {
116+ // Also allow simple string format for backward compatibility
117+ return typeof value === 'string' && value.length > 0;
118+ }
119+}
120+
121+export function getValidatedAntOnlyMetadataUserId(): string | undefined {
122+ const value = getAntOnlyMetadataUserId();
123+ if (value && !validateMetadataUserId(value)) {
124+ console.warn('ANT_ONLY_METADATA_USER_ID has invalid format. Expected JSON: {"user": "...", "job": "..."}');
125+ return undefined;
126+ }
127+ return value;
128+}
129+```
130+
131+## Usage by Internal Services
132+
133+Services like Claude Oracle should set this environment variable before launching Claude Code sessions:
134+
135+```python
136+# In Claude Oracle / coo job code
137+import os
138+import json
139+
140+# Set the metadata before spawning Claude Code
141+os.environ['ANT_ONLY_METADATA_USER_ID'] = json.dumps({
142+ "user": username, # Anthropic username
143+ "job": job_name # e.g., "claude-oracle:fluorine:vinke"
144+})
145+
146+# Then launch Claude Code session...
147+```
148+
149+Or via command line:
150+
151+```bash
152+ANT_ONLY_METADATA_USER_ID='{"user":"tedm","job":"tedm-1208-mu-g-18x"}' claude --headless ...
153+```
154+
155+## Data Flow
156+
157+```
158+┌─────────────────────────────────────────────────────────────────┐
159+│ COO Job / Oracle / Oncall / etc. │
160+│ Sets: ANT_ONLY_METADATA_USER_ID='{"user":"..","job":".."}' │
161+└─────────────────────────────────────────────────────────────────┘
162+ │
163+ ▼
164+┌─────────────────────────────────────────────────────────────────┐
165+│ Claude Code CLI │
166+│ Reads: process.env.ANT_ONLY_METADATA_USER_ID │
167+│ Adds to API calls: metadata: { user_id: "..." } │
168+└─────────────────────────────────────────────────────────────────┘
169+ │
170+ ▼
171+┌─────────────────────────────────────────────────────────────────┐
172+│ Anthropic API │
173+│ Receives: metadata.user_id in request │
174+│ Stores in: api_usage.metadata_user_id (BigQuery) │
175+└─────────────────────────────────────────────────────────────────┘
176+ │
177+ ▼
178+┌─────────────────────────────────────────────────────────────────┐
179+│ BigQuery: anthropic.api_production.api_usage │
180+│ Fields populated: │
181+│ - metadata_user_id │
182+│ - device_id (if included) │
183+│ - claude_code_session_id (if included) │
184+└─────────────────────────────────────────────────────────────────┘
185+```
186+
187+## Testing
188+
189+1. **Unit Tests**:
190+ - Test that `getAntOnlyMetadataUserId()` returns undefined when env var is not set
191+ - Test that it returns the value when set (in internal builds)
192+ - Test validation of JSON format
193+
194+2. **Integration Tests**:
195+ - Verify metadata is included in API requests
196+ - Verify tree-shaking removes the code in public builds
197+
198+3. **E2E Validation** (after deployment):
199+ - Run a Claude Code session with the env var set
200+ - Query BigQuery `anthropic.api_production.api_usage` to verify `metadata_user_id` is populated
201+
202+## Security Considerations
203+
204+1. **Internal Only**: The tree-shaking ensures this feature is not available in public builds
205+2. **No Secrets**: The metadata should not contain sensitive information
206+3. **Validation**: Input validation prevents injection attacks
207+
208+## Related Files to Modify (Internal Repo)
209+
210+Based on patterns in the bundled CLI, likely files to modify:
211+
212+1. `src/config/env.ts` or similar - Add env var reading
213+2. `src/api/anthropic.ts` or similar - Add metadata to API requests
214+3. `build.config.ts` or similar - Add build-time flag for internal builds
215+4. Tests for the above
216+
217+## References
218+
219+- Slack thread: Internal API metadata discussion
220+- BigQuery tables: `anthropic.api_production.api_usage`, `api_events`
221+- Anthropic API docs: [Messages API metadata parameter](https://docs.anthropic.com/en/api/messages)