Building a multi-spec project
Building more complex spec relationships
This guide will take you from a prototype with a single spec to a structured, scalable architecture. By the end, you’ll understand how to factor behavior into separate specs, declare dependencies between them (and their underlying code), and what project-level docs will help your project scale smoothly.
What we're building:
A spaced repetion app called memo that stores cards in a sqlite database and runs quizzes through a CLI or MCP server.
You can see a finished version of the app here.
Prerequisites
This guide assumes that you've run through our quickstart and have the latest version of Tessl installed.
Python: Any recent version is fine. We recommend using
pyenv
to manage python versions.A package manager: We recommend
uv
, butpoetry
orpip
are just as fine.A coding agent: This walkthrough will use
claude code
, but Tessl works with all the most popular agentsGit: We strongly recommend that you have version control installed and configured on all your agentic projects!
Run the following commands:
tessl init && tessl setup agent
And copy some starter quiz data:
Understand Product Requirements
Before you write a line of code — or spec! — it's important to clarify what you’re building. For complex projects, a good README
is your first artifact.
Start with sections like vision, use cases, usage, and setup experience.
Don’t worry about being perfect — the goal is to get ideas out of your head and spot inconsistencies now, so you don't find them later as bugs and incorrect assumptions
Expect this to take 20–30 minutes, it's one of the harder parts!
Work iteratively: capture what you know now, then refine with your agent as the project evolves.
Hello world
Once we have our README
, it's tempting to hand the whole thing to our agent and ask it to build everything. But this is dangerous for a few reasons:
Agents work best when they have existing examples to work from. When your project is empty, they're much more likely to go off the rails.
Agents need clear, actionable feedback on their work - its hard to untangle logic bugs when you're also struggling to install dependencies and configure your environment.
In spec-driven development, you own your project architecture. The more your agent builds at once, the harder it is to keep track of how your system works.
Our recommendation is to work with agents like you work with teammates: ask for work in small chunks that are easy to test and easy to review. Let's start with something simple:
Build a simple cli quiz tool called memo using python and Typer.
The agent should provide a work plan that looks like this:
# Plan: Create Memo CLI Quiz Tool
Build a simple CLI quiz tool called "memo" using Python and Typer framework.
## Tasks
- [ ] Bootstrap project with Python/Typer configuration using uv and pyenv
- [ ] Interview user for quiz requirements.
- [ ] Create spec for memo CLI tool
- [ ] Build initial implementation from spec
- [ ] Test the CLI tool
If it doesn't, it's fine to be more explicit in your requests:
Build a simple cli quiz tool called memo using python and Typer. Use tessl plans.
Because we're saving the plan in a file, it's easy to edit. Planning is one of the most effective ways to get good results with agents. You should review your agent's plans and expect to make edits!
Since this is our first spec, we need to review what the agent writes to make sure it matches our preferred style. We'll also add a step to search the Tessl Registry and add usage specs for any dependencies. With that, the plan looks like this:
# Plan: Create Memo CLI Quiz Tool
Build a simple CLI quiz tool called "memo" using Python and Typer framework.
## Tasks
- [ ] Bootstrap project with Python/Typer configuration using uv and pyenv
- [ ] **Search Tessl for any usage specs related to the project dependencies**
- [ ] Interview user for quiz requirements.
- [ ] Create spec for memo CLI tool **and review with user**
- [ ] Build initial implementation from spec
- [ ] Test the CLI tool
Make sure the agent reads the edits and updates its plan:
Summarize the changes I made to the plan file, then get started on the first task.
The agent will start by interviewing you about your desired tech stack. If you're used to vibe coding, this might feel a bit different — the agent doesn't go racing ahead! Tessl steers your agent to ask clarifying questions about your project requirements before it gets going. When asked, provide the following information.
For project setup (assuming you're using the recommended dependencies):
Install the latest python using pyenv, then set up uv to manage dependencies. Add typer and pytest. I want the project organized into specs/, memo/, and tests/.
For product requirements:
Load all the facts from facts.csv and run through all of them. Give me a score at the end without storing anything.
Your agent should use tessl create
to make a spec. Your results might look a bit different, but spend some time reviewing the spec. The spec format is intentionally flexible - so make it your own! This will pay dividends for all your future work. Ultimately, you should end up with something like this:
When you're ready, ask the agent to keep going with the plan. It should use tessl build
to create your hello world cli and then perform some manual testing on its own. Open a terminal and play around with the app yourself, reporting bugs or asking for tweaks.
Further prototyping
Tessl specs make it easy to explore before you commit to a final architecture. Let's try separating the quiz runner functionality into a separate module. All we need to do is add another [@generate]
link to our existing cli spec.
Update the cli.spec.md to generate a cli.py and a quiz.py module
Review the updated spec and then have your agent build it with tessl build
. For this tutorial, we already know the architecture we're aiming for. But in a new project, it's a good idea to try a few different architectures to see what your agent can build most effectively. Getting this foundation right will make all your future work a lot easier.
Adding MCP
Before we get going with the full implementation, let's work through the last piece of project setup and scaffolding: the MCP interface. First, we'll want our MCP server to reference the quiz functionality too, so let's factor that out into its own spec:
Create a spec for the quiz functionality, using the current cli spec as context. Then update the cli spec to depend on the quiz spec.
You should see a few changes:
[@generate](../memo/quiz.py)
will be replaced with[@use](./quiz.spec.md)
The quiz spec will be responsible for generating the code via
[@generate](../memo/quiz.py)
In this case, there's nothing to build because the modules already existed. Now that quiz
is refactored, let's call it with the mcp server:
Add an mcp server using fastmcp. Update the cli spec to add a memo mcp command.
Remember to review and edit the plan file generated by the agent. In this case, we end up with something like this:
# Plan: Add MCP Server Module with FastMCP
Implement an MCP server module that provides a get_next_question tool and integrates with the existing quiz module.
## Tasks
- [ ] Research existing project structure and quiz module implementation
- [ ] Install FastMCP module and usage spec
- [ ] Create spec for MCP server module with get_next_question tool
- [ ] Update CLI spec to add mcp command
- [ ] Build CLI implementation with mcp command
- [ ] Test the MCP server functionality
Let your agent run until it has a working implementation, then you can test it manually using the mcp inspector. Assuming you've been using the recommended setup:
npx @modelcontextprotocol/inspector uv run memo mcp
Try listing and running a few tools to make sure everything is working.
Designing the architecture
Now that we have the basic building blocks in place, it's time to get a bit more detailed with our system design. Create a project-architecture.md
and make sure it's linked from AGENTS.md
.
Just like your README
, expect to spend a bit of time here! You are the TL for your agent, so this is one of your key responsibilities. Generally the project architecture should contain:
Tech stack
Core objects and abstractions
Common design patterns
Desired project/folder layout
Of course, you can go much deeper with your design documents. But this is a good place to start. For us, we ended up with something like this:
Building the final implementation
This is where all our up front work really starts to pay off. With a good README
and project-architecture.md
, we can start to increase the scope that we hand to our agent:
Review the project and summarize the gaps in functionality from the README. Make a plan to implement all the missing functionality.
As usual, your main job is reviewing the implementation plan and ensuring it's sensible. Try to think about how you would build the feature - if you'd ask a co-worker to split it into a separate PR, your agent probably should too! Your plan should look something like this
If you're wondering what makes a good plan, take a look at our best practices for plans.
This task has a particularly tricky refactor: replacing the stateless quiz behavior with a database backend and a bunch of new fields. Standard refactor rules apply:
First, get the new module working in isolation.
Next, migrate existing functionality to use the new module and test that everything works.
Finally, introduce the new functionality.
Once the agent finishes working through the plan, open up the CLI — or MCP server — and try it out. Import facts.csv
and review all the new cards. When you run another review, you shouldn't get any cards because they're scheduled for future reviews.
What's next
In this tutorial, we focused on building from a single spec into a scalable architecture and touched on common files like README
and project-architecture.md
. For simplicity, we validated our work with manual testing, which is a great way to keep things loose while you're prototyping and exploring.
Last updated