Skip to main content
Gecko runs one code path in two modes. recorded and live differ only at the transport edge — same discovery, same tool selection, same request building. The only difference is where the response comes from.
ModeNetworkCostResponse source
recordednone$0synthesized from the operation’s response schema
liveyesper the APIthe real upstream API

Why recorded mode exists

The first deliverable for any wire integration is a free local simulation that can falsify it offline. Live smoke is the final check, never the primary debugger. If the agent picks the wrong endpoint or builds a malformed request, recorded mode catches it before a single network call — or a single cent — is spent.
Recorded mode proves the agent selected the right call and built a well-formed request. It does not prove the upstream returns that exact data — for that, run live. Recorded responses are schema-shaped samples, not real data.

How the sample is built

For each operation, Gecko finds the success response schema (200 / 201 / default, JSON content) and synthesizes a minimal valid instance from it. The generator is deterministic — the same schema always yields the same sample — and walks the schema sensibly:
  • honors example, then default, then the first enum value
  • follows anyOf / oneOf (first branch) and merges allOf
  • builds objects from properties, arrays from items
  • emits typed placeholders for primitives (e.g. an ISO timestamp for a date-time string), with a bounded recursion depth
This is what powers the $0 demo: many real specs ship almost no response examples, so to demo and validate without live calls, Gecko synthesizes from the schema.

Running it

uv run python -m surfcall.demo      # E2E recorded demo, $0
Or programmatically:
result = client.call(tool_name, args, mode="recorded")
# {
#   "status": 200,
#   "request": "https://.../api/odds/snapshot/123",
#   "method": "GET",
#   "data": { ... schema-shaped sample ... },
#   "mode": "recorded"
# }
Switching to live is a one-word change once you have a session:
result = client.call(tool_name, args, mode="live")
Because the path is identical, a green recorded run is a strong signal the live call will be well-formed too — the remaining unknowns are purely network and credentials.