Skip to content

feat(surf): SurfMarket / SurfChain / SurfSocial function-call tools#68

Merged
1bcMax merged 2 commits into
mainfrom
feat/surf-function-tools
May 24, 2026
Merged

feat(surf): SurfMarket / SurfChain / SurfSocial function-call tools#68
1bcMax merged 2 commits into
mainfrom
feat/surf-function-tools

Conversation

@KillerQueen-Z
Copy link
Copy Markdown
Collaborator

Why

The generic BlockRun primitive exposes Surf as a free-form path string + manual x402. Weak routed models fail two ways (both reproduced):

  1. Endpoint guessingmarket/token-ranking / market/concept-ranking → 404 → tool-failure circuit breaker disables BlockRun for the session (the original user bug).
  2. Payment hand-rolling — even after discovering the right path, a weak model (haiku) tried to hand-roll SDK payment in Bash and looped until the signature guard tripped, ~$0.58 wasted.

Prediction-market doesn't have this class of bug because it's a typed function-call tool. This PR gives Surf the same treatment.

What

Three VideoGen-style function-call tools, split by the existing skill categories:

Tool Covers
SurfMarket market, exchange, fund, news, project (rankings, fear/greed, ETF, options, liquidations, indicators, CEX, VC, DeFi)
SurfChain onchain, token, wallet (bridge/yield, gas, tx, holders, transfers, wallet intel, raw SQL)
SurfSocial social (KOL influence, mindshare, tweets, profiles)

Each tool:

  • endpoint is an enum of valid paths — the model picks, never guesses.
  • Per-endpoint required params validated with a clear error.
  • x402 signed internally (same pattern as videogen.ts) — the model never touches paths or payment.
  • Short-name tolerance — a model that drops the category prefix (fear-greed vs market/fear-greed) resolves when unambiguous; ambiguous names (ranking) return a "did you mean" list.

The generic BlockRun primitive stays for long-tail paths + future partners; these three cover the high-traffic Surf surface with guardrails.

Verification

Direct execute() (bypassing the LLM):

market/fear-greed  → $0.0010, data ✓
market/ranking     → $0.0010, data ✓
market/price (no symbol) → "needs: symbol. Missing: symbol." ✓
fear-greed (short) → auto-resolves to market/fear-greed ✓
ranking (ambiguous) → "Did you mean: market/ranking, fund/ranking, project/defi/ranking?" ✓

End-to-end (haiku, multi-endpoint prompt):

> quick crypto market pulse: Fear & Greed + top token rankings
→ activates Surf tools, calls market/fear-greed + market/ranking
→ real data (F&G 26 Extreme Fear, HYPE +9.6%, ZEC +7.0%), clean summary
→ no "gateway issues" fallback, no circuit breaker

(Same prompt on the generic primitive previously fell back to TradingMarket / looped.)

Known limitation / follow-up

The endpoint tables in surf.ts are hand-maintained from the gateway's SURF_ENDPOINTS registry — they can drift. The durable fix is to generate them (codegen from the registry, or publish the list via the shared @blockrun/llm SDK) so the gateway stays the single source of truth. Tracked as follow-up; this PR is the validated prototype.

Relationship to #67

Complementary. #67 (Surf endpoint discovery via 404 available + inlined hints) hardens the generic primitive for long-tail/ad-hoc paths. This PR gives the high-traffic Surf surface first-class function tools. Both can land; the discovery fallback still covers paths not wrapped here.

Scope

New file src/tools/surf.ts (+343) + registration in src/tools/index.ts. No change to existing tools. npm run build clean.

The generic BlockRun primitive made the agent construct free-form Surf
paths and hand-handle x402. Weak routed models failed two ways: guessing
non-existent endpoints (market/token-ranking → 404 → circuit breaker), and
after discovery, trying to hand-roll SDK payment in Bash until the loop
guard tripped (~$0.58 wasted).

Add three VideoGen-style function-call tools, split by the existing skill
categories (surf-market / surf-chain / surf-social):
- `endpoint` is an enum of valid paths — the model picks, never guesses.
- Required params per endpoint are validated with a clear error.
- x402 is signed internally (same pattern as videogen.ts) — the model
  never touches paths or payment, just fills params.
- Short-name tolerance: a model that drops the category prefix
  ("fear-greed" vs "market/fear-greed") is resolved when unambiguous;
  ambiguous names ("ranking") return a "did you mean" list.

The generic BlockRun primitive stays for long-tail paths and future
partners; these three cover the high-traffic Surf surface with guardrails.

Verified:
- Direct execute(): market/fear-greed + market/ranking return data with
  auto $0.001 payment; missing-param and unknown-endpoint give clean errors;
  short names resolve.
- End-to-end: "market pulse" prompt drives SurfMarket across fear-greed +
  ranking, returns real data (F&G 26, HYPE +9.6%), no fallback, no loop.

Known limitation: the endpoint tables are hand-maintained from the gateway's
SURF_ENDPOINTS registry. A follow-up should generate them so the gateway
stays the single source of truth (no drift).
SurfMarket worked when invoked but was activation-gated, so on a natural
prompt ("what's the crypto mood / which coins are pumping?") the agent
never reached for it — it fell back to TradingMarket prices and *guessed*
the Fear & Greed index, getting flagged twice for ungrounded claims.

PredictionMarket is already in CORE_TOOL_NAMES for exactly this reason
("what are the odds of X"). SurfMarket is the same shape of capability for
crypto market data, so it belongs in the hero surface too. SurfChain /
SurfSocial stay activation-gated (lower-frequency, long-tail).

Verified: same no-"surf"-mention prompt now drives SurfMarket on its own —
real Fear & Greed (26) + real token rankings, no hallucination flags, no
TradingMarket-only fallback.
@1bcMax 1bcMax merged commit 5b6b9da into main May 24, 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