BIP is identity, auth, and payments infrastructure for autonomous agents.
Pitch:
- Real email identity
- Real auth + long-lived session continuity
- Real web payments (x402 + checkout fill)
- One runtime for intents (
intent_create -> intent_execute -> artifacts)
This repo includes the hosted API/runtime + CLI surfaces used in the Browser Use hackathon build.
- Agent auth (
/auth/login) with invite + hCaptcha controls - Session issuance + quota enforcement
- Agent wallet provisioning + Solana deposit address
- Funding sync from inbound Solana txs (
funding_sync) - Intent lifecycle (
create,approve,execute,status,resume) - Payment rails abstraction (
x402+ browser checkout fill) - Credential/artifact outputs by reference (
secretRef,proofRef,traceId) - Treasury card refs for backend checkout flows (no raw PAN/CVV in intent payloads)
- Convex HTTP actions + Convex DB
- TypeScript CLI (
commander) - Local credential encryption (
aes-256-gcm+scrypt)
bun installbun run convex:devThis starts local Convex and writes .env.local including:
CONVEX_URLCONVEX_SITE_URL
Agents talk HTTP — no CLI install needed. Read the skill manifest to discover available intents:
curl -fsSL https://exciting-stingray-685.convex.site/skill.mdAuthenticate and start making requests:
TOKEN=$(curl -s -X POST "https://exciting-stingray-685.convex.site/auth/login" \
-H "content-type: application/json" \
-H "x-agent-id: agent-$(date +%s)" \
-d '{"inviteCode":"<invite-code>","captchaToken":"10000000-aaaa-bbbb-cccc-000000000001"}' \
| jq -r '.accessToken')Session tokens are valid for 24 hours.
Set an invite code gate on Convex:
bunx convex env set INVITE_CODES "<invite-code>"For production:
bunx convex env set --prod INVITE_CODES "<invite-code>"You can set multiple codes as a comma-separated list:
bunx convex env set --prod INVITE_CODES "code-a,code-b,code-c"Optional local convenience for CLI:
export BIP_INVITE_CODE="<invite-code>"Set environment variables on Convex for your deployment:
bunx convex env set HCAPTCHA_SECRET_KEY "<your-hcaptcha-secret>"
bunx convex env set HCAPTCHA_SITE_KEY "<your-hcaptcha-site-key>"For production:
bunx convex env set --prod HCAPTCHA_SECRET_KEY "<your-hcaptcha-secret>"
bunx convex env set --prod HCAPTCHA_SITE_KEY "<your-hcaptcha-site-key>"For test/demo mode with hCaptcha test keys, use:
HCAPTCHA_SITE_KEY=10000000-ffff-ffff-ffff-000000000001HCAPTCHA_SECRET_KEY=0x0000000000000000000000000000000000000000
Set backend environment variables:
bunx convex env set AGENTMAIL_API_KEY "<your-agentmail-api-key>"Optional (defaults to https://api.agentmail.to):
bunx convex env set AGENTMAIL_BASE_URL "https://api.agentmail.to"For production:
bunx convex env set --prod AGENTMAIL_API_KEY "<your-agentmail-api-key>"
bunx convex env set --prod AGENTMAIL_BASE_URL "https://api.agentmail.to"consent acceptconsent checkconfig:set-base-url --url <url>login --invite-code <code> [--captcha-token <token>]user retrievecreate_agentmail --email <email>delete_agentmail --inbox-id <inboxId>wallet_register --chain <chain> --address <address> [--label <label>]wallet_balance [--chain <chain>]intent_create --task <task> [--budget-usd <usd>] [--rail <rail>]intent_approve --intent-id <intentId>intent_execute --intent-id <intentId>intent_status --intent-id <intentId>run_status --run-id <runId>logout
POST /api/tools/offering_list(phase-1 static offerings + effective policy)POST /api/tools/create_intent(policy-validated for phase-1 whenintentType+providerare set)POST /api/tools/approve_intentPOST /api/tools/execute_intentPOST /api/tools/intent_resumePOST /api/tools/intent_status(now includesholdAmountCents,settledAmountCents,releasedAmountCents,fundingStatus)POST /api/tools/run_statusPOST /api/tools/spend_summary(per-agent funded/held/settled + totals by provider and intent type)POST /api/tools/treasury_card_add(admin-gated; stores backend card bycardRef)POST /api/tools/treasury_card_list(admin-gated; masked metadata only)POST /api/tools/wallet_deposit_address(returns/auto-provisions primary Solana funding address)POST /api/tools/funding_sync(operator trigger; scans inbound Solana txs and auto-credits unprocessed deposits)POST /api/tools/funding_status(shows detected inbound Solana txs and credited/uncredited state for current user)POST /api/tools/funding_mark_settled(admin-gated; credits ledger from settled Solana transfer)
For live Browser Use-backed intent execution:
export BROWSER_USE_API_KEY="<your-bu-api-key>"
# optional
export BROWSER_USE_API_BASE="https://api.browser-use.com"
export ADMIN_CARD_WRITE_TOKEN="<internal-admin-token>"
export DEFAULT_TREASURY_CARD_REF="card_ops_primary_xxxxxx"
# free | metered
export PAYMENTS_MODE="free"
# minimum budget gate in metered mode
export MIN_INTENT_BUDGET_USD="1"# 1) login
TOKEN=$(curl -s -X POST "$BASE/auth/login" \
-H "content-type: application/json" \
-H "x-agent-id: agent-$(date +%s)" \
-d '{"inviteCode":"opalbip2026","captchaToken":"10000000-aaaa-bbbb-cccc-000000000001"}' \
| jq -r '.accessToken')
# 2) fund account
curl -s -X POST "$BASE/api/tools/wallet_deposit_address" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d '{}' | jq '{address, memo, reference}'
curl -s -X POST "$BASE/api/tools/funding_sync" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d '{"maxTx":20}' | jq '{detectedCount, creditedCount, totalCreditedCents}'
# 3) create deterministic api_key_purchase intent
INTENT=$(curl -s -X POST "$BASE/api/tools/create_intent" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d '{"intentType":"api_key_purchase","provider":"elevenlabs","task":"create API key and return proof","budgetUsd":8,"rail":"auto","metadata":{"provider":"elevenlabs","accountEmailMode":"existing","targetProduct":"starter"}}' \
| jq -r '.intentId')
# 4) execute
curl -s -X POST "$BASE/api/tools/execute_intent" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d "{\"intentId\":\"$INTENT\"}" | jq '{status, provider, traceId, proofRef, credential, artifact, handoffUrl}'# 0) admin adds treasury card once (never send PAN/CVV in intent payloads)
CARD_REF=$(curl -s -X POST "$BASE/api/tools/treasury_card_add" \
-H "authorization: Bearer $TOKEN" \
-H "x-admin-token: $ADMIN_CARD_WRITE_TOKEN" \
-H "content-type: application/json" \
-d '{"label":"ops-primary","pan":"4111111111111111","expMonth":"12","expYear":"2030","cvv":"123","nameOnCard":"Ops Treasury"}' \
| jq -r '.cardRef')
# 1) agent gets deposit address (wallet auto-generated if missing)
curl -s -X POST "$BASE/api/tools/wallet_deposit_address" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d '{}' | jq '{address, memo, reference}'
# 2) send SOL on-chain to that address, then trigger auto funding sync
curl -s -X POST "$BASE/api/tools/funding_sync" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d '{"maxTx":20}' | jq '{detectedCount, creditedCount, totalCreditedCents}'
# 3) optional: inspect which txs are credited vs pending
curl -s -X POST "$BASE/api/tools/funding_status" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d '{"maxTx":20}' | jq '{detectedCount, txs}'
# 4) admin override remains available for manual settlement edits
curl -s -X POST "$BASE/api/tools/funding_mark_settled" \
-H "authorization: Bearer $TOKEN" \
-H "x-admin-token: $ADMIN_CARD_WRITE_TOKEN" \
-H "content-type: application/json" \
-d '{"userIdOrAgentId":"agent-123","amountCents":1000,"txSig":"5f...","chain":"solana"}' | jq
# 5) agent creates giftcard intent (metadata.cardRef optional if DEFAULT_TREASURY_CARD_REF is set)
INTENT=$(curl -s -X POST "$BASE/api/tools/create_intent" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d "{\"intentType\":\"giftcard_purchase\",\"provider\":\"bitrefill\",\"task\":\"buy $10 card and return fulfillment\",\"budgetUsd\":10,\"rail\":\"auto\",\"metadata\":{\"cardRef\":\"$CARD_REF\"}}" \
| jq -r '.intentId')
# 6) execute; artifacts include payment source marker only (no PAN/CVV)
curl -s -X POST "$BASE/api/tools/execute_intent" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d "{\"intentId\":\"$INTENT\"}" | jq '{status, runId, paymentSource, cardRef}'bun run typecheckRun the Bun E2E suite:
bun run test:e2eWhat it covers:
- invite-code + hCaptcha login gating
- 24-hour session issuance
- per-session API quota enforcement (
100calls) create_agentmailanddelete_agentmail- one-active-inbox-per-agent enforcement
- CLI flow (
consent,login, tool calls) - phase-1 offering registry endpoint
- create-intent policy enforcement (allowlist + caps), including
api_key_purchasemetadata contract - per-agent spend summary totals
The test harness uses local mock providers for hCaptcha and AgentMail.
It simulates AgentMail free-tier behavior with a cap of 3 active inboxes and validates that deleting an inbox frees a slot.
set either/both to mirror run lifecycle events externally:
LAMINAR_INGEST_URL(+ optionalLAMINAR_API_KEY)HUD_TRACE_URL(+ optionalHUD_API_KEY)
payload includes traceId, runId, intentId, phase (started|rail_selected|failed|confirmed), status, rail, task metadata, and timing fields.
- Offering policies are persisted in
offeringPoliciesand auto-seeded fromOFFERINGS.mdphase-1 defaults on first use. create_intentenforces:- offering registry match on (
intentType,provider) - provider allowlist per offering policy
- per-intent budget cap and per-day budget cap
api_key_purchasemetadata contract:provider(string, required)accountEmailMode(agentmail|existing, required)targetProduct(string, optional)dryRun(boolean, optional)
- offering registry match on (
- Legacy mode is preserved when both
intentTypeandproviderare omitted.