HOW_TO_BUILD_AN_AGENT
*Technical guide for creating autonomous agents on the SidebarAgent base class*
$ npx -y skills add taylorsatula/mira --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
Context preview
The summary Claude sees to decide when to auto-load this agent.
*Technical guide for creating autonomous agents on the SidebarAgent base class*
Agent definition
HOW_TO_BUILD_AN_AGENT.mdHow to Build a Sidebar Agent
*Technical guide for creating autonomous agents on the SidebarAgent base class*
Contribute It Back
Every line in this tree is agent-written, and this repository is public. When you build an agent that is **broadly useful** — not a one-off shaped around one person's accounts, data, or habits — propose opening a pull request against `origin/main` so every other MIRA installation gets it too. MIRA gets better for everyone when the agents built on one instance flow back into the shared trunk.
**Propose, never assume.** Ask the user first. Do not create a branch, commit, push, or open a PR without an explicit yes — root `AGENTS.md` Git Workflow requires it.
When to propose
| Propose a PR | Keep it local | |---|---| | Autonomously handles a problem any installer would hit | Depends on one user's accounts, mailbox, or private services | | Curates, researches, or maintains something MIRA already owns | Encodes one person's habits as if they were universal | | Generalizes a pattern the existing agents lack | Duplicates `forage` / `whilethecatsaway` / `memory_curator` | | Fixes a defect in the base class, dispatcher, or a trigger | Is scaffolding for an unfinished local feature | | — | Cannot be made safe to run unattended for strangers |
**Agents carry a higher bar than tools.** A sidebar agent runs with no human in the loop, on someone else's machine, against their real accounts. Before proposing one upstream, be able to answer: what is the worst thing it can do with its granted tools, what stops untrusted input from steering it, and what bounds its cost (`max_iterations`, timeout override, sentry gate). If the honest answer is "it has `email_tool` and full discretion", it is not ready to ship to strangers — restrict the schema first (Step 3).
The process
1. **Finish and verify locally first.** Boot gate clean, one real `WorkItem` dispatched, the trace read, the `sidebar_activity` row and trinket render confirmed, maps written. Never propose a PR for an agent that has never executed — see Verification below. 2. **Ask the user.** Say what the agent does, why it is generally useful rather than personal, what tools it holds, and exactly which files the PR would touch. 3. **On yes, branch fresh off upstream.** Never PR from `main`, and never carry unrelated local changes along.
git fetch origin
git checkout -b feat/my-agent origin/main
If you cannot push to `origin` (you cloned someone else's fork, or the repo is read-only to you), fork `taylorsatula/mira-OSS` first, add it as a remote, and target the public `main`. 4. **Stage explicit paths only.** An agent is multi-file — stage each one deliberately:
git add agents/implementations/my_agent.py \
config/prompts/agents/my_agent_system.txt \
agents/implementations/AGENTS.md \
config/prompts/AGENTS.md
# plus, only if the PR includes them:
# agents/triggers/my_trigger.py, agents/triggers/AGENTS.md,
# utils/sidebar_jobs.py, config/config.py, config/config_manager.py,
# working_memory/trinkets/my_trinket.py, cns/integration/factory.py,
# working_memory/composer.py, working_memory/trinkets/AGENTS.mdNever `git add -A` or `git add .` — a working checkout holds `data/` (including agent traces and `sidebar_activity` SQLite), scratch notes, local config, and possibly secrets. 5. **Read what you staged** with `git diff --cached --stat` and then `git diff --cached`. Hunt specifically for credentials, personal paths, usernames, mailbox addresses, and debugging leftovers. 6. **Commit** with a semantic prefix (`feat:`, `fix:`, `refactor:`) and, for non-trivial changes, `ROOT CAUSE` and `SOLUTION RATIONALE` body sections. Report the hash and file summary to the user. 7. **Push and open the PR** against `main`. Short title in the project's own voice, body covering what the agent does, its trigger path, its tool grants and guardrails, its cost bounds, and how it was verified. One concern per PR — an unrelated fix goes on its own branch. 8. **Return the user to the branch they were on.** Leave their checkout as you found it.
If your harness provides a PR-writing or git-workflow skill, load it before step 6.
Before it ships
- [ ] No secrets, tokens, mailbox credentials, or real account identifiers
- [ ] No `data/users/**`, SQLite files, agent traces, scratch notes, or local config
- [ ] No user-specific hardcoding — paths, usernames, folder names, device names, timezone assumptions
- [ ] `enabled: bool = Field(default=False)` on any new config — a contributor's agent must not start polling in someone else's install by default
- [ ] No new row in `model_configs`; the route set is CHECK-constrained to the five existing names
- [ ] `sanitize_untrusted_input = True` if it touches external content, and `build_initial_message()` reads the **sanitized** key
- [ ] `tool_schema_overrides` restricts every domain tool to the operations the rubric actually needs
- [ ] Cost bounded: `max_iterations` justified, `agent_timeout_overrides` entry present if it needs more than 120s, sentry gate if it polls speculatively
- [ ] Rubric states escalation behavior — when unsure, flag for the human rather than act
- [ ] Maps updated in the same commit (`agents/implementations/AGENTS.md`, plus `agents/triggers/`, `config/prompts/`, `working_memory/trinkets/` as touched)
- [ ] Boot gate passes from a clean checkout: `python -m utils.power_on_self_test pre-server`
- [ ] The agent was dispatched live and the trace read — not merely imported
- [ ] New external dependency justified in the PR body, or none added
This repository is AGPL-3.0; contributions land under that license.
What is a Sidebar Agent?
A **sidebar agent** is an autonomous LLM-in-a-loop that runs independently of the main conversation. Unlike tools (which execute one-shot operations) or trinkets (which passively render state), sidebar agents **act on their own** in r
Read more
How to Build a Sidebar Agent
*Technical guide for creating autonomous agents on the SidebarAgent base class*
Contribute It Back
Every line in this tree is agent-written, and this repository is public. When you build an agent that is **broadly useful** — not a one-off shaped around one person's accounts, data, or habits — propose opening a pull request against `origin/main` so every other MIRA installation gets it too. MIRA gets better for everyone when the agents built on one instance flow back into the shared trunk.
**Propose, never assume.** Ask the user first. Do not create a branch, commit, push, or open a PR without an explicit yes — root `AGENTS.md` Git Workflow requires it.
When to propose
| Propose a PR | Keep it local | |---|---| | Autonomously handles a problem any installer would hit | Depends on one user's accounts, mailbox, or private services | | Curates, researches, or maintains something MIRA already owns | Encodes one person's habits as if they were universal | | Generalizes a pattern the existing agents lack | Duplicates `forage` / `whilethecatsaway` / `memory_curator` | | Fixes a defect in the base class, dispatcher, or a trigger | Is scaffolding for an unfinished local feature | | — | Cannot be made safe to run unattended for strangers |
**Agents carry a higher bar than tools.** A sidebar agent runs with no human in the loop, on someone else's machine, against their real accounts. Before proposing one upstream, be able to answer: what is the worst thing it can do with its granted tools, what stops untrusted input from steering it, and what bounds its cost (`max_iterations`, timeout override, sentry gate). If the honest answer is "it has `email_tool` and full discretion", it is not ready to ship to strangers — restrict the schema first (Step 3).
The process
1. **Finish and verify locally first.** Boot gate clean, one real `WorkItem` dispatched, the trace read, the `sidebar_activity` row and trinket render confirmed, maps written. Never propose a PR for an agent that has never executed — see Verification below. 2. **Ask the user.** Say what the agent does, why it is generally useful rather than personal, what tools it holds, and exactly which files the PR would touch. 3. **On yes, branch fresh off upstream.** Never PR from `main`, and never carry unrelated local changes along.
git fetch origin git checkout -b feat/my-agent origin/main
If you cannot push to `origin` (you cloned someone else's fork, or the repo is read-only to you), fork `taylorsatula/mira-OSS` first, add it as a remote, and target the public `main`. 4. **Stage explicit paths only.** An agent is multi-file — stage each one deliberately:
git add agents/implementations/my_agent.py \
config/prompts/agents/my_agent_system.txt \
agents/implementations/AGENTS.md \
config/prompts/AGENTS.md
# plus, only if the PR includes them:
# agents/triggers/my_trigger.py, agents/triggers/AGENTS.md,
# utils/sidebar_jobs.py, config/config.py, config/config_manager.py,
# working_memory/trinkets/my_trinket.py, cns/integration/factory.py,
# working_memory/composer.py, working_memory/trinkets/AGENTS.mdNever `git add -A` or `git add .` — a working checkout holds `data/` (including agent traces and `sidebar_activity` SQLite), scratch notes, local config, and possibly secrets. 5. **Read what you staged** with `git diff --cached --stat` and then `git diff --cached`. Hunt specifically for credentials, personal paths, usernames, mailbox addresses, and debugging leftovers. 6. **Commit** with a semantic prefix (`feat:`, `fix:`, `refactor:`) and, for non-trivial changes, `ROOT CAUSE` and `SOLUTION RATIONALE` body sections. Report the hash and file summary to the user. 7. **Push and open the PR** against `main`. Short title in the project's own voice, body covering what the agent does, its trigger path, its tool grants and guardrails, its cost bounds, and how it was verified. One concern per PR — an unrelated fix goes on its own branch. 8. **Return the user to the branch they were on.** Leave their checkout as you found it.
If your harness provides a PR-writing or git-workflow skill, load it before step 6.
Before it ships
- [ ] No secrets, tokens, mailbox credentials, or real account identifiers
- [ ] No `data/users/**`, SQLite files, agent traces, scratch notes, or local config
- [ ] No user-specific hardcoding — paths, usernames, folder names, device names, timezone assumptions
- [ ] `enabled: bool = Field(default=False)` on any new config — a contributor's agent must not start polling in someone else's install by default
- [ ] No new row in `model_configs`; the route set is CHECK-constrained to the five existing names
- [ ] `sanitize_untrusted_input = True` if it touches external content, and `build_initial_message()` reads the **sanitized** key
- [ ] `tool_schema_overrides` restricts every domain tool to the operations the rubric actually needs
- [ ] Cost bounded: `max_iterations` justified, `agent_timeout_overrides` entry present if it needs more than 120s, sentry gate if it polls speculatively
- [ ] Rubric states escalation behavior — when unsure, flag for the human rather than act
- [ ] Maps updated in the same commit (`agents/implementations/AGENTS.md`, plus `agents/triggers/`, `config/prompts/`, `working_memory/trinkets/` as touched)
- [ ] Boot gate passes from a clean checkout: `python -m utils.power_on_self_test pre-server`
- [ ] The agent was dispatched live and the trace read — not merely imported
- [ ] New external dependency justified in the PR body, or none added
This repository is AGPL-3.0; contributions land under that license.
What is a Sidebar Agent?
A **sidebar agent** is an autonomous LLM-in-a-loop that runs independently of the main conversation. Unlike tools (which execute one-shot operations) or trinkets (which passively render state), sidebar agents **act on their own** in r
a best-effort approximation of a synthetic entity complete with all of the primatives required for long-horizon persistance. batteries included.

