Skip to content

Fix Slack agent billing and evlog context#447

Merged
izadoesdev merged 9 commits intostagingfrom
fix/slack-agent-billing-evlog
May 6, 2026
Merged

Fix Slack agent billing and evlog context#447
izadoesdev merged 9 commits intostagingfrom
fix/slack-agent-billing-evlog

Conversation

@izadoesdev
Copy link
Copy Markdown
Member

Summary

  • resolve Slack/API-key agent billing through the organization owner
  • log Autumn agent credit checks with billing customer and balance context
  • attach shared AI/RPC logging to Slack agent run evlogs
  • convert Slack internal imports to @ aliases

Verification

  • bun run check-types
  • bun run lint
  • bun run test

@vercel
Copy link
Copy Markdown

vercel Bot commented May 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
databuddy-status Ready Ready Preview, Comment May 6, 2026 11:25am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
dashboard Skipped Skipped May 6, 2026 11:25am
documentation Skipped Skipped May 6, 2026 11:25am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e1b439e0-dc4e-4c9c-85bd-a49588c2fe13

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/slack-agent-billing-evlog

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@unkey-deploy
Copy link
Copy Markdown

unkey-deploy Bot commented May 6, 2026

The latest updates on your projects. Learn more about Unkey Deploy

Name Status Preview Inspect Updated (UTC)
uptime (preview) Ready Visit Preview Inspect May 6, 2026 11:26am

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR fixes Slack/API-key agent billing by routing all org-scoped API keys through the organization owner, attaches the shared AI and RPC logging machinery to the Slack evlog context via AsyncLocalStorage, and converts internal imports to @ aliases.

  • Billing fix (execution.ts): resolveAgentBillingCustomerId now short-circuits to getOrganizationOwnerId whenever apiKey.organizationId is set, bypassing user-level billing for all org-scoped keys (not just Slack). ensureAgentCreditsAvailable gains Autumn balance/timing telemetry and a proper error re-throw path.
  • Evlog context (evlog-slack.ts, run-handler.ts, agent-client.ts, index.ts): AsyncLocalStorage wraps each Slack agent run so AI/RPC log calls inside @databuddy/ai and @databuddy/rpc automatically attach to the active Slack evlog; the Axiom drain is now guarded with try/catch to prevent drain failures from bubbling up.
  • Import aliases: All relative ../ imports within apps/slack converted to @/ path aliases; no logic changes.

Confidence Score: 4/5

Safe to merge with minor caveats — the core evlog context wiring is sound and the billing fix is well-tested, but the tsconfig change quietly removes an index-access safety net across the whole AI package.

The async-context plumbing in evlog-slack is correct: both the AI and RPC logger providers catch exceptions from getActiveSlackLog so there are no uncaught throws outside a Slack context. The billing routing change is backed by new tests. The main concern is packages/ai/tsconfig.json dropping noUncheckedIndexedAccess to make the freshly-added check-types script pass — this suppresses a category of potential type errors across the entire package going forward rather than fixing the underlying issues.

packages/ai/tsconfig.json (noUncheckedIndexedAccess disabled) and packages/ai/src/ai/agents/execution.ts (billing behavior now applies to all org-scoped API keys, not only Slack).

Important Files Changed

Filename Overview
packages/ai/src/ai/agents/execution.ts Core billing resolution changed to route all org-scoped API keys through the organization owner; credit check now logs Autumn balance and timing context.
packages/ai/tsconfig.json noUncheckedIndexedAccess disabled to allow the newly-added check-types script to pass, weakening index-access type safety across the whole package.
apps/slack/src/lib/evlog-slack.ts Adds AsyncLocalStorage-backed Slack log context with withSlackLogContext/getActiveSlackLog/setActiveSlackLog; Axiom drain now wrapped in try/catch to avoid breaking event handling.
apps/slack/src/slack/run-handler.ts handleAgentRun now wraps its try/finally in withSlackLogContext so AI/RPC logs are attached to the Slack evlog; removes premature slack_response_ok=true from queued-message path.
apps/slack/src/agent/agent-client.ts Enriches the active Slack log context at stream start with agent_chat_id, agent_source, org id, and API key id; adds agentApiKeyId to SlackRunContext.
packages/ai/src/ai/mcp/run-agent.ts Adds agent_billing_mode field to the wide event after billing resolution; minor cleanup (billingCustomerId local variable).
apps/slack/src/index.ts Registers getActiveSlackLog as the AI and RPC request logger provider so downstream logging calls attach to the active Slack evlog context.
packages/ai/src/ai/agents/execution.test.ts New tests cover: org-owner billing for API keys with and without userId, ensureAgentCreditsAvailable logging (balance fields, skip path). Good coverage of the billing change.

Sequence Diagram

sequenceDiagram
    participant Slack
    participant run-handler
    participant evlog-slack
    participant agent-client
    participant execution
    participant Autumn

    Slack->>run-handler: handleAgentRun(run)
    run-handler->>evlog-slack: createSlackEventLog(fields)
    run-handler->>evlog-slack: withSlackLogContext(eventLog, fn)
    activate evlog-slack
    Note over evlog-slack: AsyncLocalStorage.run(eventLog, fn)
    run-handler->>agent-client: agent.stream(run, options)
    agent-client->>evlog-slack: setActiveSlackLog({agent_chat_id, org_id, api_key_id})
    Note over evlog-slack: Enriches active logger via AsyncLocalStorage
    agent-client->>execution: resolveAgentBillingCustomerId(principal)
    alt apiKey has organizationId
        execution->>execution: getOrganizationOwnerId(apiKeyOrganizationId)
        Note over execution: Bills org owner for ALL org-scoped API keys
    else no apiKey.organizationId
        execution->>execution: getBillingCustomerId(userId, organizationId)
    end
    execution-->>agent-client: billingCustomerId
    agent-client->>Autumn: check(customerId, agent_credits)
    Autumn-->>agent-client: {allowed, balance}
    agent-client->>evlog-slack: mergeWideEvent({credits context})
    Note over run-handler,evlog-slack: AI/RPC loggers use getActiveSlackLog() provider
    run-handler->>evlog-slack: eventLog.emit() [in finally]
    deactivate evlog-slack
Loading

Reviews (1): Last reviewed commit: "fix(rpc): keep log context export lightw..." | Re-trigger Greptile

Comment thread packages/ai/tsconfig.json Outdated
"isolatedModules": true,
"noEmit": true,
"noUncheckedIndexedAccess": true,
"noUncheckedIndexedAccess": false,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 This flag was enabled before and protected against unsafe array-index reads (e.g. the [featureId, value] destructuring in trackAgentUsageAndBill, path[0] in rpc-log-context.ts). Disabling it to make check-types pass trades away a whole class of type-safety guarantees rather than fixing the underlying typing. Consider fixing the narrowing errors instead and re-enabling this.

Suggested change
"noUncheckedIndexedAccess": false,
"noUncheckedIndexedAccess": true,

Comment on lines +34 to +46
if (apiKeyOrganizationId) {
const customerId = await getOrganizationOwnerId(apiKeyOrganizationId);
mergeAgentBillingFields({
apiKeyId: principal.apiKey?.id,
apiKeyUserId: principal.apiKey?.userId,
billingCustomerId: customerId,
organizationId: apiKeyOrganizationId,
resolution: customerId
? "api_key_org_owner"
: "api_key_org_owner_missing",
});
return customerId;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Billing change affects all org-scoped API keys, not only Slack

When apiKey.organizationId is present the function now unconditionally routes billing to the organization owner, even for API keys that also carry a userId. This matches the Slack fix described in the PR, but resolveAgentBillingCustomerId is shared by the MCP/dashboard paths too. Any non-Slack API key that previously billed against a specific user's Autumn customer record will silently shift to billing the org owner after this change. The new test explicitly asserts this behavior for the case where userId is populated, which confirms it is intentional — worth a callout in case other consumers rely on user-level billing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant