* feat: add billing context to LLM telemetry traces
Add billing metadata (plan type, cost source, customer ID) to LLM traces in ClickHouse for cost analytics and attribution.
**Data Flow:**
- Cloud-API: Extract billing info from subscription in rate limiting, set x-billing-* headers
- Core: Parse headers into BillingContext object via dependencies
- Adapters: Flow billing_context through all LLM adapters (blocking & streaming)
- Agent: Pass billing_context to step() and stream() methods
- ClickHouse: Store in billing_plan_type, billing_cost_source, billing_customer_id columns
**Changes:**
- Add BillingContext schema to provider_trace.py
- Add billing columns to llm_traces ClickHouse table DDL
- Update getCustomerSubscription to fetch stripeCustomerId from organization_billing_details
- Propagate billing_context through agent step flow, adapters, and streaming service
- Update ProviderTrace and LLMTrace to include billing metadata
- Regenerate SDK with autogen
**Production Deployment:**
Requires env vars: LETTA_PROVIDER_TRACE_BACKEND=clickhouse, LETTA_STORE_LLM_TRACES=true, CLICKHOUSE_*
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
* fix: add billing_context parameter to agent step methods
- Add billing_context to BaseAgent and BaseAgentV2 abstract methods
- Update LettaAgent, LettaAgentV2, LettaAgentV3 step methods
- Update multi-agent groups: SleeptimeMultiAgentV2, V3, V4
- Fix test_utils.py to include billing header parameters
- Import BillingContext in all affected files
* fix: add billing_context to stream methods
- Add billing_context parameter to BaseAgentV2.stream()
- Add billing_context parameter to LettaAgentV2.stream()
- LettaAgentV3.stream() already has it from previous commit
* fix: exclude billing headers from OpenAPI spec
Mark billing headers as internal (include_in_schema=False) so they don't appear in the public API.
These are internal headers between cloud-api and core, not part of the public SDK.
Regenerated SDK with stage-api - removes 10,650 lines of bloat that was causing OOM during Next.js build.
* refactor: return billing context from handleUnifiedRateLimiting instead of mutating req
Instead of passing req into handleUnifiedRateLimiting and mutating headers inside it:
- Return billing context fields (billingPlanType, billingCostSource, billingCustomerId) from handleUnifiedRateLimiting
- Set headers in handleMessageRateLimiting (middleware layer) after getting the result
- This fixes step-orchestrator compatibility since it doesn't have a real Express req object
* chore: remove extra gencode
* p
---------
Co-authored-by: Letta <noreply@letta.com>
* auto fixes
* auto fix pt2 and transitive deps and undefined var checking locals()
* manual fixes (ignored or letta-code fixed)
* fix circular import
* remove all ignores, add FastAPI rules and Ruff rules
* add ty and precommit
* ruff stuff
* ty check fixes
* ty check fixes pt 2
* error on invalid
This fixes the asyncpg.exceptions.CharacterNotInRepertoireError that occurs
when tool returns contain null bytes (0x00), which PostgreSQL TEXT columns
reject in UTF-8 encoding.
Changes:
- Add sanitize_null_bytes() function to recursively remove null bytes from strings
- Update json_dumps() to sanitize data before serialization
- Apply sanitization in converters.py for tool_calls, tool_returns, approvals, and message_content
- Add comprehensive unit tests
Fixes#8014🤖 Generated with [Letta Code](https://letta.com)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Letta <noreply@letta.com>
Co-authored-by: Kian Jones <11655409+kianjones9@users.noreply.github.com>
* cherrypick just relevant commits?
* make work with poetry
* update poetry?
* regen?
* change tests and dev to dependency groups instead of optional extras
* Fix Poetry/UV compatibility issues
- Fix sqlite-vec dependency: Remove optional flag from Poetry section to match main deps
- Regenerate poetry.lock to sync with pyproject.toml changes
- Test both package managers successfully:
- Poetry: `poetry install --with dev --with test -E postgres -E external-tools -E cloud-tool-sandbox`
- UV: `uv sync --group dev --group test --extra postgres --extra external-tools --extra cloud-tool-sandbox`
Resolves Poetry lock sync errors and ensures sqlite-vec is available for tests.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* more robust pip install
* Fix fern SDK wheel installation in CI workflow
Replace unreliable command substitution with proper error handling:
- Check if directory exists before attempting to find wheels
- Store wheel file path in variable to avoid empty arguments
- Provide clear error messages when directory/wheels are missing
- Prevents "required arguments were not provided" error in uv pip install
Fixes: error: the following required arguments were not provided: <PACKAGE>
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* debugging
* trigger CI
* ls
* revert whl installation to -e
* programmatic HIT version insertion
* version templating properly
* set var properly
* labelling
* remove version insertion
* ?
* try using sed '2r /dev/stdin'
* version
* try again smh
* not trigger on poetry version
* only add once
* filter only for project not poetry
* hand re-construct the file
* save tail?
* fix docker command
* please please please
* rename test -> tests
* update poetry and rename group to -E
* move async into tests extra and regen lock files and add sqlite extra
* remove loading cached venv from cloud api integration
* add uv dependency to CI runners
* test removing the custom event loop
* regen poetry.lock and try to fix async tests
* wrap async pg exception and event loop tweak in plugins
* remove event loop from plugins test and remove caching from cloud-api-integration-test
* migrate all tests away from event loop for pytest-asyncio
* pin firecrawl
* pin e2b
* take claude's suggestion
* deeper down the claude rabbit hole
* increase timeout for httpbin.org
---------
Co-authored-by: Claude <noreply@anthropic.com>