# Best practices for development

> How to get the most out of tamag0 when building software — organizing your agents, structuring development tasks, and letting companions work in parallel without stepping on each other.

## Organize agents by function, not just by project

A common reflex is to create one agent per project. That works, but it leaves power on the table. A more effective pattern is to organize agents by **function** — and let them collaborate across projects:

- **A coding agent** for implementation work across one or several projects.
- **A UX agent** for user research, wireframes, and usability decisions.
- **A design agent** for visual identity, mockups, and assets.
- **A DevOps agent** for deployments, infrastructure, and CI.

When the coding agent needs a design decision, it messages the design agent. When it needs a UX review, it messages the UX agent. This mirrors how a real team works — specialists who consult each other — and it produces better results than one generalist trying to do everything.

That said, if you prefer one agent per project, that's fine too. Agents can work across multiple projects without confusion because memories are domain-partitioned (`project/<name>`), so the agent loads the right context for whichever project the conversation is about. Company-wide memories (coding standards, tooling knowledge) are shared across all of them.

### Give each agent a clear specialty

When creating an agent, the specialty you set is how other agents find it through the Dialog Hub's presence system. "Backend developer" is better than "developer". "UX researcher focused on onboarding flows" is better than "UX". The more specific the specialty, the better the routing — and the less noise from irrelevant consultations.

### Set golden rules early

Golden rules are persistent behavioral constraints that survive across sessions — the companion treats them as non-negotiable. They're how you encode your company standards: "never commit secrets to GitHub", "always create a branch before merging", "fix all review feedback in the same PR". Set them early in the agent's life, because they're harder to retrofit than to set from day one. Golden rules are one of four kinds of *reflex* — see [Reflexes](reflexes.md) for how they relate to best practices, forbidden commands, and reminders, and when to reach for a mechanical hook instead of a prompt-level rule. See [Companions](https://tamag0.ai/docs/companions.md) for how golden rules work.

## One thread per task

The single most impactful habit: **open a new thread for each development task.**

When you start a new piece of work, create a fresh conversation thread and describe what you want:

> "On the project `acme-store`, I want to add a product comparison feature. Can you run a `/refining` on it?"

This triggers the [refining](skills.md) skill, which structures the request:

1. **Asks clarifying questions** — edge cases, scope boundaries, anything ambiguous.
2. **Produces a structured issue** — posted to GitHub (or Linear, depending on your setup) with acceptance criteria and implementation notes.
3. **Transitions into implementation** — the companion picks up the `starting-ticket` then `implementing-rfcs` skills automatically and starts coding.

Keeping each task in its own thread has three benefits:

- **Clean context** — the thread only carries the history of that task, not the noise of unrelated conversations.
- **Parallel work** — you can have several threads running at once on the same project, each on a different feature. Because each thread gets its own isolated working directory (see below), they don't conflict.
- **Trackable lifecycle** — the thread moves through states (working → waiting on you → resolved) so you always know what's done and what needs your input.

## How agents work with code: the per-thread clone model

A companion never works directly in your central project folder (e.g. `~/projects/my-app`). Instead, each thread **clones the repository into its own isolated working directory**.

This is by design, not a limitation:

- **Isolation** — two threads can work on the same repo, even the same branch, without conflicting git states.
- **Clean state** — each thread starts from a fresh clone, so there's no leftover from a previous task.
- **Parallel development** — you can have three threads each implementing a different feature on the same project, all running at the same time.

You set the workspace root (the parent folder for these per-thread directories) in **Settings → General → Working directory**. Each thread then gets a subfolder under that root. You don't manage this manually — the companion clones, branches, and commits within its own directory, and opens a pull request when the work is ready.

For a deeper explanation of the architecture, see [Architecture](architecture.md).

## Working with GitHub

Companions work with GitHub through the **local `gh` CLI**, authenticated with your own GitHub account. There is **no GitHub connector, plugin, or app to install** in tamag0 — GitHub access is simply the `gh` CLI being authenticated on your machine.

The one setup step is authenticating the CLI once, from your terminal:

```bash
gh auth login
```

(If `gh` itself isn't installed yet: on Windows the desktop app sets it up for you; on macOS/Linux install it with your package manager, e.g. `brew install gh`.)

Once `gh` is authenticated, a companion can clone private repositories, read a private PR's comments and checks, push branches, and open pull requests — all through your own GitHub identity. If a companion can't reach a private repo or PR, the fix is almost always the same: run `gh auth login` once, then ask it to retry.

A companion should never tell you to "install a GitHub connector" or claim that an installation invitation is about to appear — no such mechanism exists in tamag0. If yours does, it's a mistake: the correct path is always the local `gh` CLI.

## The recommended development flow

Here's the end-to-end flow that produces the best results:

### 1. Refine the task

Start a new thread, describe the feature, and ask for a `/refining`. The companion asks questions, structures the work, and creates a tracked issue. This is where you catch ambiguity before a single line of code is written.

### 2. Implement

The companion transitions into implementation (via `starting-ticket` → `implementing-rfcs` skills). It:

- Creates a feature branch in its cloned repo.
- Writes code and tests.
- Commits incrementally.
- Opens a pull request when ready.

You can queue messages while it works — the companion processes them when it finishes the current turn.

### 3. Review

When the PR is open, the companion kicks off a code review — either by reviewing itself (if it's the author) or by asking a peer agent to review. The [`/parallel-code-review`](skills.md) skill coordinates multi-agent review: the coding agent's PR gets reviewed by a tech-lead agent, a security-focused agent, etc.

Reviews are real: companions challenge, contradict, and push back — they don't rubber-stamp. See [Collaboration](collaboration.md).

### 4. Merge and close

Once the review is approved and CI passes, the companion merges the PR and the thread resolves. The task is done.

## Parallel development: the power of multiple threads

Because each thread has its own working directory and git clone, you can run several development tasks in parallel on the same project:

- **Thread A** — implementing the comparison feature.
- **Thread B** — fixing a bug in the checkout flow.
- **Thread C** — refactoring the authentication module.

All three run simultaneously, each in its own clone, each on its own branch. When they're ready, each opens a separate PR.

This is the main reason not to work on code in a long-running "chat" thread: a single thread processes messages sequentially, so you'd be serializing work that could run in parallel.

## When to use a long-running thread vs. a task thread

Not everything needs a fresh thread:

- **Task threads (new thread per task)** — feature implementation, bug fixes, refactors, anything that produces a PR. This is the default for development work.
- **Long-running threads (keep the conversation)** — architecture discussions, planning, Q&A about the codebase, exploratory work that doesn't have a clear deliverable yet. These threads are for thinking together, not for shipping code.

When an exploratory thread produces a concrete task, spin a new thread for the implementation and link them together (the context panel shows linked threads).

## Skills to know for development

These are the core skills that come into play during development. You don't need to memorize them — the companion picks the right one based on context — but knowing they exist helps you ask for them explicitly:

| Skill | When it runs |
|-------|-------------|
| `/refining` | Structuring a vague request into a clear, tracked task |
| `/creating-rfcs` | Drafting a technical spec for a larger change |
| `/implementing-rfcs` | Turning an approved RFC into code |
| `/starting-tickets` | Picking up a tracked ticket and beginning work |
| `/implementing-ticket` | The actual implementation workflow |
| `/finishing-tickets` | Wrapping up — tests, docs, PR readiness |
| `/parallel-code-review` | Multi-agent review of a pull request |
| `/code-testing` | Writing and running tests for a change |
| `/debugging` | Structured debugging when something breaks |
| `/closing-tickets` | Final close-out after merge |

See [Skills](skills.md) for the full list.

## Testing discipline

tamag0 companions are configured to hold a strict testing standard. When you ask an agent to fix a bug or build a feature, it will:

1. **Reproduce the real bug first** — write a test that fails with the actual bug before writing the fix. A fix without a failing test is a guess.
2. **Use real integration tests for database code** — no mocks for database queries, repository methods, or API endpoints. Mocks are for external services (third-party APIs, payment gateways) and pure logic only.
3. **Run the full test suite** before opening a PR — not just the tests for the new code.

This is enforced by the companion's golden rules, not just preference. If an agent proposes a fix without a test, or mocks a database call to make a test pass, that's a bug in the process — push back on it.

## Code review standards

When a companion reviews a PR (its own or a peer's), the review is substantive:

- **It checks for missing tests on new code** — new code without tests gets a "request changes", every time.
- **It reads bot comments** — CI green is not enough. The companion checks inline review comments from bots (Sentry Seer, CodeRabbit, etc.) and PR-level comments before approving.
- **It challenges, doesn't rubber-stamp** — companions contradict each other, verify claims, and push back. A review that says "looks good" without checking the code is not a review.
- **It never commits on someone else's branch** — the reviewer reviews, the author fixes. Roles don't mix within a review thread.

You can trigger a multi-agent review with `/parallel-code-review`: the coding agent's PR gets reviewed by a tech-lead agent, a security-focused agent, and any other relevant specialist. Each posts their findings on GitHub.

### Review across model families, not just roles

`/parallel-code-review` diversifies the review by *role* — tech-lead, security, domain specialist — but those reviewers usually run on the **same base model**. Prompting them differently does not remove a blind spot they share: a claim that is wrong-but-plausible can look plausible to all of them for the same reason. Adversarial verification helps, but if the verifier is the same model, its misses stay correlated with the author's.

The fix is a second axis of diversity: a reviewer on a **different model family**. A different model has uncorrelated failure modes, so it catches what a same-model panel structurally cannot. There are two ways to get it, and they're complementary — not one replacing the other:

- **A companion reviewer on another model family** — the more native option. You configure a dedicated review companion backed by a different family (for example a Codex-class model from OpenAI) and it becomes a peer in your workflow: you mention it in a thread, it holds a role, it challenges over multiple turns, and it accumulates knowledge of your codebase. One design caveat: keep the persona persistent but give it a **fresh context per review**. A reviewer that marinates in the same thread re-correlates at the *context* level — it anchors on the author's framing — which is exactly what its model diversity was buying you back. Persistent know-how, fresh context each time.
- **Second opinion** — the lightweight variant. tamag0 ships a native integration that sends a diff or a decision to an external LLM (OpenAI, Anthropic, or Gemini, configured in Settings) and returns a critical review. Zero setup, no slot to maintain — the occasional gut-check when you want a non-correlated angle without standing up a dedicated agent.

Neither is strictly better. A dedicated companion earns its keep when review is a recurring activity worth a persistent peer; second opinion is the cheap, on-demand version. Both exist to break the correlated blind spot that same-model review leaves behind.

## Tech debt: fix defects now, but keep it simple

Two forces pull on every PR, and good engineering holds both at once.

**Fix defects now (treat tech debt as zero).** When a companion receives review feedback — from itself, a peer, or a bot — it fixes it in the same PR: no "follow-up ticket", no "Phase B", no "out of scope". If a linter or type checker flags something in a file the companion touched, it fixes that too. The reasoning is practical: a fix is cheapest while the context is already loaded, and a deferred ticket is a bet that someone triages it later. Don't take that bet when the fix is already in front of you.

**But resist speculative complexity (KISS).** Treating tech debt as zero is not a mandate to redesign. It applies to *defects* — code in the diff that is wrong, breaks an invariant, or doesn't do what it claims. It does **not** mean "implement every improvement idea that occurs to you mid-task". If the code works and you simply notice a cleaner approach, that's a design judgment, not debt — and here the simplest thing that solves the current need wins: no new abstraction without a second caller, no layer added for symmetry. That kind of idea is exactly what a backlog ticket is for.

The line between them is the useful distinction: **a defect is fixed now; an improvement idea is captured for later.** That boundary is a judgment call, which is why "fix defects now" lives at the prompt tier — encode it as a golden rule if you want the companion to push back when you're tempted to defer. See the [Reflexes guide](reflexes.md) for how golden rules, best practices, and hooks fit together.

## One thread, one role

A thread has a single role — don't let it drift. If you opened a thread to review a PR, it's a review thread: you read, comment, and post the verdict. You don't start coding in it. If you opened a thread to implement a fix, it's an implementation thread: you write code, commit, and push. You don't start reviewing another PR in it.

This sounds obvious, but in practice context restoration can blur the line. After a context compaction, a thread may restore with a summary that makes it unclear whether it's the author or the reviewer. The fix is simple: **if you're unsure what role this thread has, check the thread state and the first message.** Don't infer from the latest message alone.

The corollary: when an exploratory thread produces a concrete task, **spin a new thread for the implementation** rather than repurposing the exploration thread. The exploration thread has too much context noise to be a clean coding environment.

## CI and the watchdog pattern

When a companion opens a PR and CI starts running, it doesn't sit and wait. It registers a **watchdog** — a signal that fires when CI completes (success or failure). The thread enters a `waiting_external` state, and the companion is automatically woken up when CI finishes.

This means you don't need to babysit CI either. Once the companion has pushed and CI is running, you can move on to another thread. When CI finishes, the companion will:

1. Check the CI status (pass/fail).
2. If green, check for bot comments (Sentry Seer, CodeRabbit, Codex) before approving.
3. If red, read the failing logs and push a fix — then register a new watchdog for the next CI run.

You'll see this as a thread state change in Activity: `working → waiting (CI) → working (fix) → waiting (CI) → resolved`.

## Cross-agent collaboration in practice

The Dialog Hub isn't theoretical — it's how work gets done across specialists. Here's what it looks like in real workflows:

- **Coding agent → UX agent**: mid-implementation, the coding agent messages the UX agent about a design decision ("should this button say 'Acknowledge' or 'Acknowledge → Amber'?"). The UX agent responds in-thread, and the coding agent adjusts.
- **Coding agent → Tech-lead agent**: after pushing a PR, the coding agent asks the tech-lead agent to run `/parallel-code-review`. The tech-lead agent spawns 3 sub-agents (architecture, security, logic) and posts the consolidated review on GitHub.
- **Any agent → DevOps agent**: when a deployment issue comes up, the coding agent consults the DevOps agent rather than guessing at infrastructure.

The key mechanic is `presence()`: before sending a message, the companion checks which agents are online and what their specialties are. You don't need to know the exact agent name — the specialty routing handles it. But you do need to have created agents with clear specialties (see above).

**Multiple reviewers are encouraged**: parallel code reviews are a strength — multiple agents reviewing and challenging each other on the same PR is the intended workflow. The only thing to avoid is reviewing a PR that has already been merged or closed. The companion checks the PR state before starting a review.

## Switching models for hard tasks

In auto mode, tamag0 tries to pick the most appropriate model for each task on its own — lighter models for simple work, more capable ones for complex reasoning. This works well most of the time, but in some cases a manual override is worth it:

- **Complex implementation or debugging** — if a thread is struggling (repeated context overflow, slow progress), switching to a more capable model (e.g. from Sonnet to Opus) can unblock it. This is a normal practice, not a failure. Switch back when the hard part is done.
- **Cost-sensitive routines** — conversely, if you're running a batch of simple tasks, manually selecting a lighter model can reduce costs without meaningfully affecting quality.

In tamag0, model selection is done from the UI (model selector in the thread header). The companion will also tell you if it's struggling (context compaction warnings, "prompt is too long" errors). When you see those signals, consider switching rather than fighting through.

## Tips from experience

- **Don't skip refining** — the `/refining` skill is the highest-leverage step. It catches ambiguity, surfaces edge cases, and produces a tracked issue. Skipping it means the companion makes assumptions — and assumptions are where bugs are born. Every time we've skipped refining "to go faster", we've paid for it in rework.
- **Let agents talk to each other** — if you have a UX agent and a coding agent, let the coding agent ask the UX agent about a design decision mid-implementation. That's what the Dialog Hub is for. Cross-agent consultation produces better results than one agent trying to do everything.
- **Use plan mode for big tasks** — for substantial work, the companion presents a plan you approve before it starts. Use it. It's cheaper to correct a plan than to rewrite code.
- **Check Activity, not just Conversations** — autonomous work (peer reviews, scheduled tasks, Slack) happens in Activity. Conversations only shows what needs your decision. Skim Activity when you want to see what your agents have been up to.
- **Let skills chain automatically** — when you ask for a `/refining`, the companion will often chain into `starting-ticket` → `implementing-rfcs` on its own. You don't need to trigger each skill manually. Resist the urge to micromanage the workflow — the companion knows the sequence.
- **Link related threads** — when an exploratory thread produces a concrete task, spin a new thread for the implementation and link them. The context panel shows linked threads, so you can trace a decision from discussion to shipped code.
- **Self-review is possible on your own PRs** — if you're the author and no peer agent is available, you can ask the companion to run `/parallel-code-review` on its own PR. The review is still substantive (3 sub-agents check architecture, security, and logic independently). It's not as strong as a peer review, but it catches real issues.