mirror of
https://github.com/msitarzewski/agency-agents.git
synced 2026-09-21 17:05:53 +03:00
fix(aider): CONVENTIONS.md is a roster index, not 3.8 million characters of agents (#871)
Aider loads a conventions file into context and keeps it there for the whole
session — that is what the file is for, and the docs say to load it with
--read so prompt caching can hold it. This integration concatenated every
agent body into it. At 279 agents that is 3,816,372 characters, roughly a
million tokens. No model takes that. Anyone who ran
./scripts/install.sh --tool aider
got a CONVENTIONS.md that either blows the context window on the first turn
or bills for a million tokens trying.
CONVENTIONS.md is now the roster index it was described as: one entry per
agent with the name, the description, the division, and the path to the
agent file. 96,823 characters, down from 3.8 million. The header explains
how to pull a single agent's full instructions into the session:
/read-only /path/to/agency-agents/engineering/engineering-frontend-developer.md
Naming an agent in a prompt still works the way it did — the description is
what the model needed for that, and it is still there.
test-convert-outputs.sh now holds the index to being an index: it fails if
CONVENTIONS.md grows past 250,000 characters, if it does not list exactly
one path per roster agent, or if any path it prints does not resolve. The
existing round-trip check on the accumulated file still covers the names and
descriptions.
This commit is contained in:
@@ -733,7 +733,7 @@ The Agency works natively with Claude Code, and ships conversion + install scrip
|
||||
- **[Gemini CLI](https://github.com/google-gemini/gemini-cli)** -- `.md` agent files -> `~/.gemini/agents/`
|
||||
- **[OpenCode](https://opencode.ai)** — `.md` agent files → `.opencode/agents/`
|
||||
- **[Cursor](https://cursor.sh)** — `.mdc` rule files → `.cursor/rules/`
|
||||
- **[Aider](https://aider.chat)** — single `CONVENTIONS.md` → `./CONVENTIONS.md`
|
||||
- **[Aider](https://aider.chat)** — `CONVENTIONS.md` roster index → `./CONVENTIONS.md`
|
||||
- **[Windsurf](https://codeium.com/windsurf)** — single `.windsurfrules` → `./.windsurfrules`
|
||||
- **[OpenClaw](https://github.com/openclaw/openclaw)** — `SOUL.md` + `AGENTS.md` + `IDENTITY.md` per agent
|
||||
- **[Qwen Code](https://github.com/QwenLM/qwen-code)** — `.md` SubAgent files → `~/.qwen/agents/`
|
||||
@@ -926,7 +926,10 @@ See [integrations/cursor/README.md](integrations/cursor/README.md) for details.
|
||||
<details>
|
||||
<summary><strong>Aider</strong></summary>
|
||||
|
||||
All agents are compiled into a single `CONVENTIONS.md` file that Aider reads automatically.
|
||||
`CONVENTIONS.md` is the roster index — every agent's name, description, and the
|
||||
path to its full instructions. Aider keeps a conventions file in context for the
|
||||
whole session, and the 279 bodies together are about a million tokens, so the
|
||||
file lists the agents rather than inlining them.
|
||||
|
||||
```bash
|
||||
cd /your/project
|
||||
@@ -938,6 +941,11 @@ Then reference agents in your Aider session:
|
||||
Use the Frontend Developer agent to refactor this component.
|
||||
```
|
||||
|
||||
When you want an agent's full instructions, read its file in:
|
||||
```
|
||||
/read-only /path/to/agency-agents/engineering/engineering-frontend-developer.md
|
||||
```
|
||||
|
||||
See [integrations/aider/README.md](integrations/aider/README.md) for details.
|
||||
</details>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ supported agentic coding tools.
|
||||
- **[OpenCode](#opencode)** — `.md` agent files in `opencode/`
|
||||
- **[OpenClaw](#openclaw)** — `SOUL.md` + `AGENTS.md` + `IDENTITY.md` workspaces
|
||||
- **[Cursor](#cursor)** — `.mdc` rule files in `cursor/`
|
||||
- **[Aider](#aider)** — `CONVENTIONS.md` in `aider/`
|
||||
- **[Aider](#aider)** — `CONVENTIONS.md` roster index in `aider/`
|
||||
- **[Windsurf](#windsurf)** — `.windsurfrules` in `windsurf/`
|
||||
- **[Kimi Code](#kimi-code)** — YAML agent specs in `kimi/`
|
||||
- **[Qwen Code](#qwen-code)** — project-scoped `.md` SubAgents in `.qwen/agents/`
|
||||
@@ -171,8 +171,10 @@ See [cursor/README.md](cursor/README.md) for details.
|
||||
|
||||
## Aider
|
||||
|
||||
All agents are consolidated into a single `CONVENTIONS.md` file that Aider
|
||||
reads automatically when present in your project root.
|
||||
`CONVENTIONS.md` is the roster index — name, description, and the path to each
|
||||
agent's full instructions. Aider keeps a conventions file in context for the
|
||||
whole session, so the file lists the agents instead of inlining a million
|
||||
tokens of them.
|
||||
|
||||
```bash
|
||||
cd /your/project && /path/to/agency-agents/scripts/install.sh --tool aider
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
# Aider Integration
|
||||
|
||||
The full Agency roster is consolidated into a single `CONVENTIONS.md` file.
|
||||
Aider reads this file automatically when it's present in your project root.
|
||||
`CONVENTIONS.md` is the roster index: every agent's name, what it is for, its
|
||||
division, and the path to its full instructions.
|
||||
|
||||
## Why an index and not the agents
|
||||
|
||||
Aider keeps a conventions file in context for the whole session — that is the
|
||||
point of the file. The 279 agent bodies together are about 3.8 million
|
||||
characters, roughly a million tokens, so a conventions file holding all of them
|
||||
does not fit in any model and costs a fortune in the attempt.
|
||||
|
||||
The index is about 97,000 characters (~24k tokens). Load it read-only so aider
|
||||
marks it cacheable, and pull in a single agent's full instructions when you
|
||||
actually need them.
|
||||
|
||||
## Install
|
||||
|
||||
@@ -11,26 +22,30 @@ cd /your/project
|
||||
/path/to/agency-agents/scripts/install.sh --tool aider
|
||||
```
|
||||
|
||||
## Activate an Agent
|
||||
## Use an agent
|
||||
|
||||
In your Aider session, reference the agent by name:
|
||||
Naming the agent is usually enough — its description is already in context:
|
||||
|
||||
```
|
||||
Use the Frontend Developer agent to refactor this component.
|
||||
```
|
||||
|
||||
When you want the agent's full instructions, read its file into the session.
|
||||
The index gives you the path:
|
||||
|
||||
```
|
||||
Apply the Reality Checker agent to verify this is production-ready.
|
||||
/read-only /path/to/agency-agents/engineering/engineering-frontend-developer.md
|
||||
```
|
||||
|
||||
## Manual Usage
|
||||
|
||||
You can also pass the conventions file directly:
|
||||
## Manual usage
|
||||
|
||||
```bash
|
||||
aider --read CONVENTIONS.md
|
||||
```
|
||||
|
||||
`--read` marks the file read-only and lets aider cache it when prompt caching
|
||||
is enabled, so the index is not re-sent on every turn.
|
||||
|
||||
## Regenerate
|
||||
|
||||
```bash
|
||||
|
||||
+23
-8
@@ -14,7 +14,7 @@
|
||||
# gemini-cli — Gemini CLI subagent files (~/.gemini/agents/*.md)
|
||||
# opencode — OpenCode agent files (.opencode/agents/*.md)
|
||||
# cursor — Cursor rule files (.cursor/rules/*.mdc)
|
||||
# aider — Single CONVENTIONS.md for Aider
|
||||
# aider — Single CONVENTIONS.md roster index for Aider
|
||||
# windsurf — Single .windsurfrules for Windsurf
|
||||
# openclaw — OpenClaw workspaces (integrations/openclaw/<agent>/SOUL.md)
|
||||
# qwen — Qwen Code SubAgent files (~/.qwen/agents/*.md)
|
||||
@@ -568,11 +568,21 @@ trap 'rm -f "$AIDER_TMP" "$WINDSURF_TMP"' EXIT
|
||||
cat > "$AIDER_TMP" <<'HEREDOC'
|
||||
# The Agency — AI Agent Conventions
|
||||
#
|
||||
# This file provides Aider with the full roster of specialized AI agents from
|
||||
# The Agency (https://github.com/msitarzewski/agency-agents).
|
||||
# The roster of specialized AI agents from The Agency
|
||||
# (https://github.com/msitarzewski/agency-agents): each one's name, what it is
|
||||
# for, and where its full instructions live.
|
||||
#
|
||||
# To activate an agent, reference it by name in your Aider session prompt, e.g.:
|
||||
# "Use the Frontend Developer agent to review this component."
|
||||
# Aider keeps a conventions file in context for the whole session, so this is an
|
||||
# index and not the agents themselves. Inlining every body would make this file
|
||||
# about 3.8 million characters, which no model will take.
|
||||
#
|
||||
# To use an agent:
|
||||
# 1. Name it in your prompt — "Use the Frontend Developer agent to review
|
||||
# this component." The description below is usually enough for that.
|
||||
# 2. For its full instructions, pull the agent file into the session:
|
||||
# /read-only /path/to/agency-agents/engineering/engineering-frontend-developer.md
|
||||
#
|
||||
# Paths below are relative to an agency-agents checkout.
|
||||
#
|
||||
# Generated by scripts/convert.sh — do not edit manually.
|
||||
|
||||
@@ -590,12 +600,16 @@ HEREDOC
|
||||
|
||||
accumulate_aider() {
|
||||
local file="$1"
|
||||
local name description body
|
||||
local name description source division
|
||||
|
||||
name="$(get_field "name" "$file")"
|
||||
description="$(get_field "description" "$file")"
|
||||
body="$(get_body "$file")"
|
||||
source="${file#"$REPO_ROOT"/}"
|
||||
division="${source%%/*}"
|
||||
|
||||
# One index entry per agent, not the agent. A conventions file is read into
|
||||
# every request; the bodies together are 3.8 million characters and this
|
||||
# index is about 90,000.
|
||||
cat >> "$AIDER_TMP" <<HEREDOC
|
||||
|
||||
---
|
||||
@@ -604,7 +618,8 @@ accumulate_aider() {
|
||||
|
||||
> ${description}
|
||||
|
||||
${body}
|
||||
Division: ${division}
|
||||
Full instructions: ${source}
|
||||
HEREDOC
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -18,7 +18,7 @@
|
||||
# gemini-cli -- Install agents to ~/.gemini/agents/
|
||||
# opencode -- Copy agents to .opencode/agents/ in current directory
|
||||
# cursor -- Copy rules to .cursor/rules/ in current directory
|
||||
# aider -- Copy CONVENTIONS.md to current directory
|
||||
# aider -- Copy the CONVENTIONS.md roster index to current directory
|
||||
# windsurf -- Copy .windsurfrules to current directory
|
||||
# openclaw -- Copy workspaces to ~/.openclaw/agency-agents/
|
||||
# qwen -- Copy SubAgents to ~/.qwen/agents/ (user-wide) or .qwen/agents/ (project)
|
||||
@@ -926,6 +926,8 @@ install_aider() {
|
||||
fi
|
||||
install_file "$src" "$dest"
|
||||
ok "Aider: installed -> $dest"
|
||||
dim " CONVENTIONS.md is the roster index. Load one agent's full instructions with"
|
||||
dim " /read-only $REPO_ROOT/<path shown in the index>"
|
||||
$SELECTION_ACTIVE && warn "Aider: single-file format — team/agent filtering N/A (installs the full roster)."
|
||||
warn "Aider: project-scoped. Run from your project root to install there."
|
||||
}
|
||||
|
||||
@@ -353,6 +353,31 @@ if split_bad:
|
||||
else:
|
||||
ok(f"openclaw: all {N} agents keep every source fenced block whole in one output file")
|
||||
|
||||
# --- Layer A (context budget): the Aider index has to stay an index ----------
|
||||
# Aider keeps a conventions file in context for the whole session. Inlining the
|
||||
# agent bodies made CONVENTIONS.md 3.8 million characters, which no model will
|
||||
# take, so it carries one index entry per agent instead: description plus the
|
||||
# path to the real file. Two things have to hold for that to be worth anything —
|
||||
# the file stays small enough to load, and every path it prints resolves.
|
||||
AIDER_INDEX_CEILING = 250_000
|
||||
aider_index = os.path.join(OUT, "aider", "CONVENTIONS.md")
|
||||
if os.path.isfile(aider_index):
|
||||
text = open(aider_index, encoding="utf-8").read()
|
||||
if len(text) > AIDER_INDEX_CEILING:
|
||||
bad(f"aider: CONVENTIONS.md is {len(text):,} characters — it is loaded into "
|
||||
f"every request, so it has to stay an index, not the agents themselves")
|
||||
paths = re.findall(r"^Full instructions: (.+)$", text, re.M)
|
||||
dangling = sorted({p for p in paths if not os.path.isfile(os.path.join(R, p))})
|
||||
if len(paths) != N:
|
||||
bad(f"aider: CONVENTIONS.md points at {len(paths)} agent files, roster has {N}")
|
||||
elif dangling:
|
||||
for d in dangling[:3]:
|
||||
bad(f"aider: CONVENTIONS.md points at a file that does not exist: {d}")
|
||||
if len(dangling) > 3:
|
||||
bad(f"aider: ...and {len(dangling)-3} more dangling paths")
|
||||
elif len(text) <= AIDER_INDEX_CEILING:
|
||||
ok(f"aider: index is {len(text):,} characters and all {N} agent paths resolve")
|
||||
|
||||
# --- Layer A (app-facing): every SOURCE frontmatter strict-parsed above -------
|
||||
for m in src_bad[:5]: bad(m)
|
||||
if len(src_bad) > 5: bad(f"...and {len(src_bad)-5} more source frontmatter problems")
|
||||
|
||||
Reference in New Issue
Block a user