This is a submission for the Sanity Challenge, Path One: Ship an Agent That Queries Real Content
What I Built
GovCon Intelligence — an agent that answers real questions about US
federal contractors (who works with which agency, how much they've been
paid, whether they're growing or shrinking) by querying a live, structured
Sanity dataset through Sanity Context MCP. Not a summary of documents — a
real relational query over contractor documents that reference
agency documents.
The brief was blunt: "if a keyword search would have gotten you the same
answer, aim higher." So the question I asked myself building this was: what
can I ask that a flat-text search genuinely cannot answer?
"Which contractors work with the Department of Defense and are not
decreasing in growth?"
That's a join, not a lookup. It needs to filter contractors by a boolean on
their own field (growthTrend != "decreasing") and by whether any of
their referenced agency documents has a specific name. No amount of
full-text search over a JSON blob gets you that. Real result, from real
data, first try:
| Contractor | DoD amount | Growth |
|---|---|---|
| Booz Allen Hamilton | $42.9B | stable |
| Accenture Federal Services | $7.54B | stable |
| Deloitte Consulting | $7.16B | stable |
The data is real, not a fixture: I pulled it live from my own
Federal Contractor Intelligence
Apify actor, which queries USAspending.gov directly, and pushed the output
into Sanity as contractor/agency documents with genuine references
(not flattened strings). Lockheed Martin's $622B lifetime value in the demo
is a real US government spending record.
Demo
Live, no login, no setup: https://govcon-intelligence-seven.vercel.app
Try asking:
- "Who has the highest lifetime contract value?"
- "Show me contractors with a declining growth trend"
- "Which contractors work with NASA?"
Every answer is a live groq_query call against the real dataset — nothing
is canned. The demo runs on a free-tier LLM key (NVIDIA, openai/gpt-oss-20b,
no card required) so anyone judging this can run it without paying for
anything, and it's rate-limited to 15 questions/hour/IP to keep that key
usable for everyone.
Code
Repo is private (I keep all my repos private as a personal practice), so
here's the core of it directly — the whole agent loop is deliberately small:
# agent.py — the loop: ask the LLM, let it call groq_query on the live
# MCP endpoint, feed the real result back, repeat until it has an answer.
def ask(question):
messages = [{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": question}]
for i in range(6):
msg = llm_call_openai_format(messages, allow_tools=(i < 5))
messages.append(msg)
tool_calls = msg.get("tool_calls")
if not tool_calls:
cleaned = _clean(msg.get("content"))
if cleaned:
return cleaned
break
for tc in tool_calls:
args = json.loads(tc["function"]["arguments"])
mcp_result = mcp_call("tools/call",
{"name": "groq_query", "arguments": args})
tool_text = mcp_result["result"]["content"][0]["text"]
messages.append({"role": "tool", "tool_call_id": tc["id"],
"content": tool_text})
# Forced final answer, tools off — "no match" is a valid, honest answer
messages.append({"role": "user", "content":
"Based only on the query results above, give your final answer now."})
final = llm_call_openai_format(messages, allow_tools=False)
return _clean(final.get("content")) or "No matching contractors found."
# mcp_call — talks to the real Sanity Context MCP endpoint over HTTP
def mcp_call(method, params):
body = json.dumps({"jsonrpc": "2.0", "id": 1, "method": method,
"params": params}).encode()
req = urllib.request.Request(
SANITY_MCP_URL, data=body, method="POST",
headers={"Authorization": f"Bearer {SANITY_ORG_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream"})
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read())
Flask serves a small dark-themed chat UI in front of it (live stats bar,
markdown tables, source citation on every answer) — deployed on Vercel.
How I Used Sanity
Schema is two document types, deliberately kept small so the reference
relationship is the whole point:
// contractor: name, uei, totalLifetimeValue, growthTrend, leadScore,
// exclusionStatus, and topAgencies[] — an array of
// { agency: reference -> agency, amount: number }
//
// agency: name, isDoD
I pointed Sanity Context at my own Sanity dataset (GROQ mode, not a
crawled Knowledge Base — the content already lives in Sanity as real
documents, so there was nothing to crawl) and created an MCP endpoint scoped
to _type in ["contractor", "agency"]. The agent calls two of the tools
Context exposes: initial_context (to learn the schema on first turn) and
groq_query (to actually answer). The system prompt is explicit that it may
only state numbers the tool returned — never estimate.
Three things broke on the way that are worth being honest about:
-
Sanity Context requires a deployed Studio app, not just a deployed
schema — I hit a hard
-32004error until I ransanity deployagainst a Studio actually built onsanity@6(my first template was v3, which doesn't qualify). - The model I originally wired had been retired from NVIDIA's catalog
since I last used it — found the current one by checking the live
/v1/modelslist instead of guessing. -
gpt-oss's harmony format occasionally leaked an internalcommentary to=functions...fragment into the answer instead of using the structuredtool_callsfield, and separately could burn all its tool-call turns chasing a genuinely-empty result. Fixed both at the agent layer rather than papering over them in the UI — see the_clean()strip and the forced tools-off final turn in the code above.
Sanity Project Details
Project ID: 6t5rf0s6, dataset production.
MCP endpoint name: govcon-intelligence-agent (GROQ mode).
Agent Session
(Optional — will add a curated Claude Code session transcript via the DEV agent-session uploader before publishing, and remember to hit "Make Public.")
Top comments (0)