Skip to content

Latest commit

 

History

History
117 lines (85 loc) · 5.05 KB

File metadata and controls

117 lines (85 loc) · 5.05 KB

Agent Architecture

The .md files in this repo are runtime prompt artifacts, not documentation. server.py loads them at startup and injects their content into MCP tool descriptions and prompts. Editing them changes what the agent is instructed to do. README.md is the only human-facing documentation.

Contributing

This repo uses GitHub Flow: all changes go through a branch + PR, never committed directly to main. main has branch protection enforced — direct pushes are rejected.

  1. Create a branch for your change (git switch -c <branch>) before the first commit. Never commit on main and open a PR afterward — the squash-merge will leave local main permanently diverged from origin/main.
  2. Open a PR against main
  3. Merge via the GitHub UI (squash merge preferred)

After a PR merges

This repo squash-merges, so the merged commit on origin/main has a different SHA than the local feature commits. Clean up with reset, not pull:

git switch main
git fetch origin
git reset --hard origin/main
git branch -D <feature-branch>

Do not git pull on main when local main has commits matching the just-merged PR — pull will create a merge commit because the squash changed the SHA. If you must pull, use git pull --ff-only so divergence fails loudly instead of silently merging.

Deployment

The MCP server runs on the NRP Nautilus Kubernetes cluster.

  • Prod: https://duckdb-mcp.nrp-nautilus.io — 2 replicas, k8s/deployment.yaml
  • Dev: https://dev-duckdb-mcp.nrp-nautilus.io — 1 replica, k8s/dev-deployment.yaml
  • Resources: 16 Gi RAM requested, up to 160 Gi / 16 CPU per pod
  • STAC catalog: https://s3-west.nrp-nautilus.io/public-data/stac/catalog.json (set via STAC_CATALOG_URL env var)
  • Ingress: HAProxy with CORS enabled, 10-minute query timeout, 1-hour SSE tunnel timeout

Rollout workflow

Merge to main → redeploy dev only:

kubectl apply -f k8s/dev-deployment.yaml
kubectl rollout restart deployment/dev-duckdb-mcp -n biodiversity

Tag a release → redeploy prod:

kubectl apply -f k8s/deployment.yaml
kubectl rollout restart deployment/duckdb-mcp -n biodiversity

kubectl apply must precede rollout restart — a git push alone does not update the cluster.


This project uses two distinct, asynchronous AI agent processes. Do not confuse them.


Process 1: Real-time MCP Tool (Small LLM)

A lightweight open-source LLM serves user requests in real time via the MCP tool. It has no memory between requests. Its only context is what is injected at call time.

Files it reads (injected as prompts):

  • query-setup.md — required DuckDB setup SQL, must run before every query
  • query-optimization.md — short, actionable query-writing rules
  • datasets.md — STAC catalog summary, dataset paths, column schemas
  • assistant-role.md — role and response style instructions

Rules for editing these files:

  • Write for a small, stateless model with limited context
  • Instructions must be short, concrete, and unambiguous
  • No debugging advice, no explanation of DuckDB internals, no "check X before Y"
  • No meta-commentary about why rules exist — just the rules
  • Every example must be a correct, copy-pasteable query

Process 2: Asynchronous Evaluation (Claude)

A separate, asynchronous process uses Claude to review logs from real user sessions, identify slow or incorrect queries, diagnose root causes, and update the small LLM's instructions.

Files it reads:

  • Real-time query logs and timing data from production
  • optimization-design-notes.md — developer notes on DuckDB behavior and benchmarks
  • AGENTS.md — this file

Files it writes:

  • query-optimization.md, query-setup.md — updated instructions for the small LLM
  • optimization-design-notes.md — updated technical findings

Rules for this process:

  • When a query is slow, check whether it follows all rules in query-optimization.md before diagnosing infrastructure, DuckDB behavior, or S3 limitations
  • Benchmark queries used to test a rule must themselves follow that rule (e.g., a benchmark testing "h0 in join" must actually have h0 in the join)
  • Do not edit query-optimization.md with debugging checklists, developer notes, or explanations of DuckDB internals — that content belongs in optimization-design-notes.md
  • A claim that a rule in query-optimization.md is wrong requires a correctly structured benchmark that violates only that rule and nothing else

Failure mode to avoid

In March 2026, a small LLM generated a query omitting h0 from a join (violating the rule in query-optimization.md). The resulting slow query was diagnosed as "S3 DPP is broken" rather than "the query violated the h0-in-join rule." Hours of investigation followed, producing optimization-design-notes.md content that incorrectly characterized the rule as wrong. A subsequent Claude session read those notes and tried to remove the correct rule from query-optimization.md.

The fix is this document: keep the two processes and their files clearly separated.