← First Pair Library

22 The Goshawk Interoperability Release

Everything to this point describes the kernel that shipped as 0.2.0 “Peregrine”: a library and a CLI that could load, project, govern, and audit — but that nothing else could reach. Release 0.3.0 “Goshawk” is the interoperability release: the same governed semantics, now reachable over a network, over the Model Context Protocol, and across languages with real cryptography on both sides.

22.1 Real Signatures, Verified Across Languages

The Python port originally carried demonstration digests where signatures belonged. Goshawk replaces them with real Ed25519 keys, derived deterministically from agent seeds exactly the way TypeSec derives them in Rust: the SHA-256 of the seed becomes the private key, and the public key is published as a W3C did:key verification method on every envelope. An envelope now names the key that can verify it.

The two implementations verify each other with no shared state. Rust reconstructs Python’s documented signing payload (querygraph-typedid-signing-v1), resolves the did:key, and checks the signature — including recomputing Python’s canonical JSON byte-for-byte, sort_keys, compact separators, ensure_ascii escapes and all. Rust can also mint envelopes in the same format from the same seeds, so the equivalence suite proves both directions: Python signs and Rust verifies; Rust signs and Python verifies; a tampered envelope fails on either side. Where the crypto extra is absent, Python labels its digests unsigned:sha256: so nothing can mistake a hash for a signature.

22.2 A Service Surface: the /v1 API

Goshawk gives the platform its first network surface, the beginning of the querygraphd shape sketched at the end of this book. querygraph serve exposes /v1: health, four-layer Navigator bundles, the QGLake story with its full evidence chain, envelope verification, a semantic-model registry (models/import/osi, models/import/croissant, models, search), and answer. A Semantic Croissant document POSTed to the registry projects into an OSI model the same way in Rust as in Python, and search walks names, descriptions, ai_context, semantic types, and ontology terms.

Governed routes can demand proof. With --require-auth, importing a model or asking for an answer requires a signed TypeDID envelope in the x-qg-envelope header — its action fixed to invoke, its resource bound to the exact request path, and its payload bound to the SHA-256 of the request body, so an envelope can be neither replayed against another endpoint nor attached to a different body. A failed check returns a receipt that explains the contract; a denial is a document, not a mystery. The Python client mints these headers with two lines of querygraph.api_auth.

22.3 MCP: One Server, Every Framework

The Model Context Protocol is how agent frameworks discover tools in 2026, and Goshawk speaks it from both languages. querygraph mcp-serve in Python exposes the governed layer through the official SDK; the Rust binary carries a dependency-free MCP implementation over stdio. Both offer the same surface: search the semantic model, resolve metrics with dialect fallback, check access (the RBAC+ODRL dual gate, where a denial returns a receipt rather than an error), build Navigator bundles, run the governed story, verify envelopes, and answer questions. Any MCP client — Claude, LangChain, PydanticAI, LlamaIndex, CrewAI — reaches all of it with zero adapter code.

For frameworks that speak function-calling rather than MCP, TypeDidAgent.to_tool_schema() exports standard JSON-Schema tool definitions in OpenAI and Anthropic flavors, and the LangChain adapter gained async variants. Every adapter returns the envelope with the answer; nothing hands back a bare string.

22.4 The Agent Card

The agent runs in this book always labeled their protocol typedid/a2a. Goshawk makes the label honest: both implementations publish a Linux Foundation Agent2Agent card — served at /.well-known/agent-card.json, printed by agent-card — declaring the same five skills and a security scheme that documents the TypeDID envelope contract. The card is a cross-language contract; the equivalence suite asserts the two implementations publish identical skills.

22.5 Conformance, Proven Rather than Asserted

Goshawk vendors the official OpenLineage 2-0-2 JSON Schema and validates generated events against it, with format checking on. The very first run of that validator caught a real nonconformance: the spec requires run.runId to be a UUID, and both implementations were emitting prefixed hashes. Both now derive run ids as deterministic UUIDv5 values under a shared QueryGraph namespace — the same seed produces the same UUID in either language, pinned by a fixture test — and the equivalence suite schema-validates the events both CLIs emit. That is the difference between asserting interoperability and proving it.

22.6 The Governed Navigator Loop

Release 0.4.0 “Sentinel” — the governed-answer release that follows Goshawk — adds the loop this book has been building toward. GovernedNavigatorLoop in Python takes a question; searches the semantic model by name, synonym, and bigram; gates every matched dataset through RBAC+ODRL and collects the receipts; plans SQL only over allowed sources; names the denied sources in the prompt as explicitly off-limits; synthesizes with any Callable[[str], str] — an OpenAI-compatible helper binds Ollama, vLLM, llama.cpp, or LM Studio — or deterministically when no model is given; and returns the answer inside a signed envelope with a schema-valid OpenLineage event and an Ed25519 attestation. The deterministic path is the golden baseline: the same governance, with or without a language model in the loop.