feat(events): support LANGWATCH_PROJECT_ID via X-Project-Id header#619
feat(events): support LANGWATCH_PROJECT_ID via X-Project-Id header#6190xdeafcafe wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for multi-project LangWatch API keys by allowing both the Python and JavaScript event reporters to send a project scope identifier via X-Project-Id when configured, while standardizing authentication on Authorization: Bearer <api_key>.
Changes:
- Python: add
project_idsupport (env + constructor) and conditionally emitX-Project-Id; remove legacyX-Auth-Token. - JavaScript: add
projectIdplumbing fromrun()→EventBus→EventReporter, conditionally emittingX-Project-Id; switch toAuthorization: Bearer .... - Tests/docs: expand Python request-header tests to cover
X-Project-Idbehavior and bearer-only auth.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| python/tests/test_event_reporter.py | Updates header assertions for bearer-only auth and adds coverage for X-Project-Id emission and env fallback. |
| python/scenario/config/langwatch.py | Introduces project_id setting under the LANGWATCH_ env prefix. |
| python/scenario/_events/event_reporter.py | Adds project_id resolution and conditionally includes X-Project-Id; removes X-Auth-Token dual-emit. |
| javascript/src/runner/run.ts | Extends LangWatch runtime config to include projectId and passes it into the event system. |
| javascript/src/events/event-reporter.ts | Switches to bearer auth and conditionally emits X-Project-Id when configured. |
| javascript/src/events/event-bus.ts | Extends EventBus constructor config shape to accept/pass through projectId. |
| javascript/src/config/env.ts | Adds LANGWATCH_PROJECT_ID to the validated environment schema. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
LangWatch is moving to API keys that aren't bound to a single project; clients must send the project ID separately so the server can scope the request. Both event reporters now accept project_id/projectId (with LANGWATCH_PROJECT_ID env var) and emit X-Project-Id when set. Also switches authentication to Authorization: Bearer only and drops the legacy X-Auth-Token dual-emit on both reporters — the new server contract is bearer-only.
Adds parity with the Python suite — checks Authorization: Bearer is sent, X-Auth-Token is absent, X-Project-Id is sent only when projectId is configured, POST is skipped when apiKey is empty, and setUrl is returned from a successful response.
58badcd to
51a9a31
Compare
|
Automated low-risk assessment This PR was evaluated against the repository's Low-Risk Pull Requests procedure and does not qualify as low risk.
This PR requires a manual review before merging. |
Why
LangWatch is moving to API keys that aren't bound to a single project; clients must send the project ID separately so the server can scope the request. Both event reporters currently send only an API key, so multi-project keys can't authorise.
What changed
LANGWATCH_PROJECT_IDenv var +project_id/projectIdconfig to the Python and JS event reporters, with the same resolution order asapi_key(explicit → env → default empty).Authorization: Bearer <api_key>only and drop the legacyX-Auth-Tokendual-emit on both reporters — the new server contract is bearer-only.X-Project-Id: <project_id>only when configured; project-bound API keys keep working with no extra config.Test plan
python/tests/test_event_reporter.py— added three tests forproject_id(explicit, env fallback, env→explicit precedence). Updated existing tests to assertAuthorization: Bearer …instead ofX-Auth-Token. All 11 tests pass.javascript/src/events/__tests__/event-reporter.test.ts— new file. Five tests:Authorization: Beareris sent andX-Auth-Tokenis absent;X-Project-Idis sent only whenprojectIdis configured; POST is skipped whenapiKeyis empty;setUrlis returned from a successful response.pnpm typecheckis clean for the touched files; pre-existing voice-module errors (missingffmpeg-static,elevenlabs,@amiceli/vitest-cucumber) are unchanged frommain.How I can prove I was successful
No playable artifact — see Test plan. Auth header behaviour is covered by both the Python and JS suites; the two reporter implementations mirror each other.