Skip to main content
Gecko is a control plane, not a data plane. It holds the API’s surface, the generated tool defs, and correctness metadata — and never the data flowing through. That single invariant is what makes the rest of the design coherent.

The flow

Gecko architecture — a control plane, never a data plane. An AI agent (a goal, no API docs) asks the Gecko comprehension layer (the control plane) 'what can this API do for X?'. Inside, four stages run in order: ingest (OpenAPI — the surface only) → catalog (intent → endpoint) → tools (question-shaped, auth hidden) → access (session handshake). The access stage injects auth into the real API — the only line crossing from the control plane into the data plane. The agent then calls the real API directly and receives the data back directly; that data never passes through Gecko.
The agent calls the real API directly for data. Gecko injects credentials and stays out of the data path.

Invariants

Control plane, never data plane

Stores the API surface, tool defs, and correctness metadata only — never response payloads, user data, or secrets.

The engine is API-agnostic

Everything API-specific reduces to data (the spec) plus one adapter seam, Session.auth_headers(). Adding an API doesn’t touch ingest/catalog/tools/caller.

One code path, two modes

recorded and live differ only at the transport edge. The free offline simulation comes first; live smoke is the final check.

Auth is invisible to the agent

Tool defs never expose auth headers. The agent describes intent; Gecko injects credentials at call time.

Module map

The comprehension logic is the product and lives in the package; the MCP server, the client, and the scripts are thin transport.
ModuleResponsibility
gecko/ingest.pyOpenAPI 3.x → normalized Operation / Param ($ref resolution, cycle/depth guarded)
gecko/catalog.pyLexical capability search (intent → endpoint)
gecko/tools.pyOperation → question-shaped agent tool defs (auth hidden)
gecko/caller.pytool + args → correct PreparedRequest (stdlib urllib)
gecko/access.pySession.auth_headers() — the engine/adapter seam; two-token session
gecko/sample.pydeterministic schema → example (powers $0 recorded mode)
gecko/client.pyAgentApiClientsearch / list_tools / prepare / call
gecko/mcp_server.pyMcpSurface — the agent-facing MCP surface
gecko/validator.pyreplay + first-call-correct check + JSONL outcome log (metadata only)
gecko/evaluate.pytask-based first-call-correct scorecard (top-1 / top-5 / well-formed)
gecko/demo.pyrun() (recorded, $0) + live_demo()

The one seam that matters

Adding a new API should not require touching ingest, catalog, tools, or the caller. The only API-specific code is, at most, an auth adapter — an object that implements:
def auth_headers(self) -> dict[str, str]: ...
A public API uses the built-in no-auth adapter (returns {}); a paywalled API supplies a session that returns its tokens. See Access & auth.

Outcome logging (control-plane safe)

The validator and the evaluation harness append outcome metadata only — tool name, rank, ok/reason — to a JSONL log. They never write response payloads. Turning that metadata into a richer, multi-API correctness signal is V2 work and is not live today; see Status.

Security posture

  • Ingested spec/doc content is treated as untrusted input.
  • URLs are validated before fetching (no SSRF — private/loopback/link-local ranges and non-http schemes blocked).
  • Secrets come from the environment/session and are never logged or persisted; errors redact tokens before they’re raised.
  • Stdlib-first networking (urllib); minimal dependencies, so the engine ports anywhere.