Compound Engineering¶
Compound Engineering is a development philosophy built on a simple premise: each piece of work you do should make the next piece of work easier. In traditional software development, context, patterns, and institutional knowledge often exist only in developers' heads. Compound Engineering externalizes that knowledge — into rules, prompts, SDKs, and documentation — so that AI tools can apply it automatically and every new feature benefits from everything that came before.
The name is intentional. Just like compound interest, the gains start small but accelerate over time. A rule file written today saves five minutes on every future feature. An SDK method written once eliminates ten future debugging sessions. Documentation written now means AI tools generate correct code on the first try instead of the fifth.
The Core Idea¶
"Make your next task easier than your last one."
In a Compound Engineering workflow, you don't just ship features — you invest in the scaffolding around them. After every non-trivial piece of work, you ask: What did I just learn that I can encode so a human or AI doesn't have to rediscover it?
The answers take different forms:
| What you learned | How you encode it |
|---|---|
| How to correctly call the Gaia streaming API | SDK method + docstring |
That EventSource only supports GET | Cursor rule: "always use fetch for SSE" |
| The right FastAPI error handler pattern | Template in .cursor/rules/ |
| How to structure a Marketplace AppSpec | Documented example + checklist |
| Common mistakes AI makes with our codebase | ai-workflow-tips.md pitfalls section |
Each encoding is a deposit. Future you — and your AI assistant — draws from that account.
The Three Layers¶
Compound Engineering operates across three reinforcing layers:
Layer 1: Encoded Knowledge (Rules & Prompts)¶
The lowest-friction way to make AI work correctly is to tell it exactly how your project works — once, in a rules file — rather than repeating it in every prompt.
In this project, .cursor/rules/ encodes: - Authentication patterns (API key in header, never in frontend) - SDK usage (always use GaiaClient, never raw httpx) - Streaming patterns (fetch + ReadableStream, not EventSource) - Error handling (catch GaiaError subclasses, map to HTTP status) - Response serialization (.model_dump(by_alias=True) for camelCase)
When these rules exist, an AI assistant generating a new endpoint does it correctly the first time. Without them, you'd debug the same patterns repeatedly.
Habit: After fixing a bug or making an architecture decision, ask: "Should I add this to the rules file so it never happens again?"
Layer 2: Reusable Abstractions (SDK & Templates)¶
The second layer is your actual code. The Gaia SDK in this project is a compound engineering artifact — it wraps the raw REST API so that every application built on it gets authentication, error handling, retry logic, and streaming for free.
Without the SDK, each example would have its own slightly-different HTTP client, its own error handling, its own streaming implementation. Bugs would be fixed in one place and missed in three others. With the SDK, you fix it once and every consumer benefits.
Habit: When you write code that a third example would need, promote it to the SDK. When you write a second Dockerfile that looks like the first, template it.
Layer 3: Living Documentation¶
The third layer is documentation that AI tools can read and reason about. This guide is itself a compound engineering investment: because it exists and is structured, AI tools like Cursor and Claude Code can give accurate, project-specific answers instead of generic ones.
Documentation compounds when it's: - Accurate — reflects the actual code, not an earlier version - Specific — includes real examples, not just concepts - Discoverable — linked from code, indexed in search, referenced in rules - Maintained — updated alongside the code it documents
Habit: When you change a pattern, update its documentation in the same commit. A stale doc is worse than no doc.
How This Project Applies It¶
Every piece of this project is a compound engineering artifact:
build-with-gaia/
│
├── sdk/python/gaia_sdk/ ← Layer 2: One SDK, all examples benefit
│ ├── client.py ← Streaming, auth, retry — written once
│ └── exceptions.py ← Error hierarchy — used everywhere
│
├── .cursor/rules/ ← Layer 1: Rules encode hard-won patterns
│ └── gaia-development.mdc ← AI reads this before generating code
│
├── examples/ ← Layer 2 + 3: Working templates
│ ├── 01-hello-gaia/ ← Verified, runnable starting points
│ └── ...
│
└── docs/ ← Layer 3: Living knowledge base
├── 04-building-your-app/ ← Patterns explained with context
└── 08-marketplace-deployment/ ← New knowledge encoded immediately
When a new developer joins, they don't start from scratch. They start from the compound position of everyone who came before.
When an AI tool generates code, it generates code that reflects weeks of decisions about Gaia patterns — because those decisions are encoded in rules and documentation it can read.
Applying It to Your Own Gaia Project¶
You don't need this project's full structure to practice Compound Engineering. Start with these habits:
Start a Rules File Early¶
Create .cursor/rules/my-project.mdc on day one. Populate it with whatever you've learned so far. It doesn't need to be long — even five rules change AI code quality dramatically.
# My Gaia Project Rules
- Use GaiaClient from gaia_sdk, never raw httpx
- API key comes from os.environ["GAIA_API_KEY"], never hardcoded
- All Gaia routes use async/await; never use synchronous httpx in FastAPI handlers
- Streaming uses fetch + ReadableStream on frontend (not EventSource)
- Dataset names are passed as a list even when querying a single dataset
Build the SDK First¶
Before writing your first application, write the Gaia client wrapper. Even a thin one:
class MyGaiaClient:
async def ask(self, dataset: str, query: str) -> str:
... # handles auth, error mapping, timeout
async def ask_stream(self, dataset: str, query: str) -> AsyncIterator[str]:
... # handles SSE parsing, reconnect
Your first app takes longer. Your second app takes half as long. By the third, you're not thinking about plumbing at all.
Document Decisions, Not Just APIs¶
When you make a non-obvious decision, write a sentence about why. Future you — and your AI — will encounter the same question:
# Using fetch + ReadableStream instead of EventSource because EventSource
# only supports GET requests and our streaming endpoint requires POST
# (query body too large for URL parameters).
That comment prevents the same decision from being unmade by an AI refactor three months later.
Treat Checklists as Compound Artifacts¶
Every non-obvious deployment or integration step is a candidate for a checklist. The Marketplace Checklist in this guide exists because deployments are infrequent and the gotchas are easy to forget. Write it once; use it every time.
The Multiplier Effect¶
Here's the compound engineering math for this project:
| Artifact | Time to create | Time saved per use | Uses per year | Net return |
|---|---|---|---|---|
gaia_sdk SDK | ~8 hours | ~2 hours debugging avoided | 20+ | 10x |
| Cursor rules file | ~1 hour | ~15 min per feature | 100+ features | 25x |
| Example 01 (Hello Gaia) | ~2 hours | ~1 hour setup avoided | 50+ | 25x |
| Marketplace checklist | ~30 min | ~45 min per deployment | 10+ | 15x |
| This documentation | ~40 hours | ~30 min per question | 500+ | 6x |
None of these returns are guaranteed — they depend on whether the artifacts stay accurate and get used. But the compounding is real: a codebase with good rules, a clean SDK, and living documentation genuinely produces features faster over time, not slower.
Further Reading¶
- Using Cursor Rules — How the rules layer is implemented in this project
- AI Development Workflow — The day-to-day loop powered by compound artifacts
- The Gaia Client Library — The SDK as a compound engineering investment