An agent-facing AutoGTM API: keys, dollar budgets, inbox, suppress lists, import - #77
Merged
Merged
Conversation
…sts, import Adds /api/v1/autogtm/*, shaped like Explee's AutoGTM API so an agent that already drives that product can drive this one with a base URL and a key. Every route translates onto code that was already here — campaigns, the policy engine, the approval path, credits, the importer, analytics — and there is still exactly one way to send. Underneath: workspace API keys (migration 0038, hashed, shown once, cannot mint keys); USD daily limits stored beside the action caps the engine enforces, with CONTACT_PRICE_USD as the exchange rate; a project-level allocator that splits a ceiling across campaigns by reply rate on every worker tick; suppression by email and domain through one shared key builder; and a policy change so that answering someone who wrote to us is not paced like cold outreach (still human-approved, still capped). llms.txt and openapi.json are rendered from one table and served keyless; a test refuses a documented route that does not exist. The hand-recorded execute path now attributes its interaction to the card's campaign. Not built on purpose: lead data (buy per credit) and a pre-warmed sending domain pool (the real ops burden). See the README section. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ralyodio
marked this pull request as ready for review
September 21, 2026 17:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
An agent-facing API shaped the way Explee's AutoGTM API is shaped, so an agent that already knows how to drive that product can drive ours with a base URL and a key. Everything on it is a translation onto code that was already here: campaigns, the policy engine, the approval path, credits, the importer, analytics. There is still exactly one way to send.
Read it the way an agent would:
GET /api/v1/public/llms.txtthenGET /api/v1/public/openapi.json. Both are keyless and rendered from one table (apps/api/src/autogtm-docs.ts); a test refuses a documented route that does not exist.Surface
/api/v1/autogtm/*need_reply/replied/sent/unsubscribedtabs, full thread, reply, per-lead note.GET /autogtm/hot-leadsacross campaigns withsincepolling.What had to be built underneath
api_keys, migration 0038).og_live_…secrets hashed like sessions, presented asX-API-KeyorBearer, acting with the owner's current role. A key cannot mint keys. Minted on/settingsorPOST /api/v1/api-keys.RequestActor.credentialsays which path a caller came in by.CONTACT_PRICE_USDis the cheapest credit pack per credit. A daily USD limit is stored onbudget_jsonbesidemaxActionsPerDay = floor(usd / price), so the existing engine enforces it on every send.packages/pipeline/src/project-budgets.tsreconciles project ceilings into campaign caps each worker tick and synchronously after any budget or autopilot change: autopilot on splits by smoothed reply rate with a 20% even exploration slice; off only scales hand-set budgets down under the ceiling.isFollowUp && conversationOpen. Nothing setisFollowUpbefore;recheckPolicynow sets it forreplycards and forexpected_goal = 'continue_conversation'. 7b still routes such a send toallow_with_approval, and the daily cap, budget and suppression gates still bind. The API reply card issend_emailbecause the capability matrix has no email/replypair.email:anddomain:;matchKeysForPersonis the single builder the pipeline, cadence runner and API repo now share.interactions.campaign_idnull; it now carries the card's campaign.Tests
bun run checkis green: format, typecheck, 1,594 tests across 112 files (baseline 1,544). New: domain arithmetic and allocator, pipeline budgets and suppression keys, policy follow-up exemption, API keys end to end through the real resolver, and the AutoGTM routes end to end against a migrated database including a reply that leaves through a stub mailer and one refused for a suppressed lead.Deliberately not in this PR
packages/providers.🤖 Generated with Claude Code