Skip to content

feat(tools): typed Phone + Voice tools — fixes agent discovery for phone/voice#58

Merged
1bcMax merged 1 commit into
mainfrom
feat/phone-voice-agent-tools
May 18, 2026
Merged

feat(tools): typed Phone + Voice tools — fixes agent discovery for phone/voice#58
1bcMax merged 1 commit into
mainfrom
feat/phone-voice-agent-tools

Conversation

@KillerQueen-Z
Copy link
Copy Markdown
Collaborator

Summary

Phone and voice endpoints were previously only reachable via the generic `blockrun` primitive — the agent had to know to POST `/v1/phone/numbers/list` or `/v1/voice/call` by string and hand-craft the body shape. In practice this meant:

  1. Models often refuse because no tool's name pattern-matches "make a phone call" / "buy a phone number"
  2. Even when models try, they discover via `.well-known/x402` (which currently omits phone/voice — see BlockRunAI/blockrun#24) and conclude the endpoints don't exist
  3. Combined with microCompact clearing prior `tool_result`s, Opus literally retracted true earlier responses ("I made that up, sorry") in repro testing

This PR adds 8 typed tools wrapping the same `/v1/phone/` and `/v1/voice/` endpoints, named to match user intent — same pattern as `ImageGen` / `VideoGen` / `ExaSearch` / `SearchX`.

New tools

Tool Cost Endpoint
`ListPhoneNumbers` $0.001 POST /v1/phone/numbers/list
`BuyPhoneNumber` $5 POST /v1/phone/numbers/buy
`RenewPhoneNumber` $5 POST /v1/phone/numbers/renew
`ReleasePhoneNumber` free POST /v1/phone/numbers/release
`PhoneLookup` $0.01 POST /v1/phone/lookup
`PhoneFraudCheck` $0.05 POST /v1/phone/lookup/fraud
`VoiceCall` $0.54 POST /v1/voice/call (Bland.ai)
`VoiceStatus` free GET /v1/voice/call/{id}

Each `spec.description` spells out cost, use case, required fields, and the Buy-number-first requirement for `VoiceCall`. Same x402 payment flow as `src/tools/exa.ts` (Base + Solana). `VoiceStatus` is the only GET, free — no payment signing path.

Repro this fixes

Verified end-to-end today with Opus 4.7 in Franklin agent:

```
Turn 1: "list my BlockRun phone numbers"
→ blockrun POST /v1/phone/numbers/list → real number, real tx hash
Turn 2: "now call +1 213-361-0872"
→ tool_result from turn 1 was already cleared by microCompact
→ Opus distrusts its own memory, GETs /.well-known/x402 to verify
→ manifest doesn't list phone (gateway bug, separate PR)
→ Opus concludes earlier success was hallucination, retracts
```

With this PR Opus picks `VoiceCall` from the tool list in turn 2 (name match → "call"), never opens discovery, dials directly.

Tests

`npm test` — all 399 tests pass. `npm run build` clean.

No new tests added — the tools are thin wrappers around the same x402 path that `exa` / `blockrun` tools already use, covered by their existing test suites.

Related

  • BlockRunAI/blockrun#24 — gateway-side fix adding phone/voice to `.well-known/x402` manifest (avoids the discovery failure root cause)
  • microCompact in `src/agent/compact.ts:592` is too aggressive on structured `tool_result`s with high info density (phone numbers, tx hashes, wallet addresses). Separate issue worth filing — whitelist tool_result content under a size threshold.

🤖 Generated with Claude Code

…etc.)

Phone and voice were previously only reachable via the generic `blockrun`
primitive — the agent had to know to POST /v1/phone/numbers/list or
/v1/voice/call by string and hand-craft the body shape. In practice this
meant models either (1) refused outright because no tool's name pattern-
matched "make a phone call", or (2) tried to discover the schema by
GETing /.well-known/x402 — which currently omits phone/voice — and
concluded the endpoints don't exist.

This adds 8 typed tools wrapping the same endpoints, named to match
intent:

  ListPhoneNumbers     — $0.001  POST /v1/phone/numbers/list
  BuyPhoneNumber       — $5      POST /v1/phone/numbers/buy
  RenewPhoneNumber     — $5      POST /v1/phone/numbers/renew
  ReleasePhoneNumber   — free    POST /v1/phone/numbers/release
  PhoneLookup          — $0.01   POST /v1/phone/lookup
  PhoneFraudCheck      — $0.05   POST /v1/phone/lookup/fraud
  VoiceCall            — $0.54   POST /v1/voice/call    (Bland.ai)
  VoiceStatus          — free    GET  /v1/voice/call/{id}

Each spec.description spells out the use case, cost, and required fields
explicitly (incl. that VoiceCall needs a wallet-owned `from` number from
BuyPhoneNumber first). This matches the existing ImageGen/VideoGen/
ExaSearch/SearchX pattern — agents grep tool names and select on the
first hit instead of opening discovery manifests.

x402 payment flow mirrors src/tools/exa.ts (Base + Solana). VoiceStatus
is the only GET, and it's free — no payment signing path.

Repro for the discovery failure mode this fixes:
  1. User: "list my BlockRun phone numbers"
  2. Opus 4.7 with old tool list: calls blockrun → real number returned
  3. User: "now call +1..."
  4. Opus loses tool_result to compaction, distrusts memory, GETs
     /.well-known/x402, doesn't see phone, retracts the earlier answer.

With this PR Opus picks VoiceCall by name in step 3, never opens the
discovery manifest, and the conversation flows naturally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@KillerQueen-Z KillerQueen-Z marked this pull request as draft May 18, 2026 01:36
@KillerQueen-Z KillerQueen-Z marked this pull request as ready for review May 18, 2026 01:40
@1bcMax 1bcMax merged commit 465b249 into main May 18, 2026
2 checks passed
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