ARF - Agents Router Framework for Hierarchical Context Management
ARF - Agents Router Framework for Hierarchical Context Management
ARF (Agents Router Framework) is a hierarchical context management system for AI coding agents that automatically discovers and routes to specialized AGENTS.md files across multiple projects. Instead of maintaining a single monolithic context file, ARF enables modular, project-specific agent contexts that scale as your codebase grows.
Problem Solved: When working across multiple repositories (PhD dissertation, NNT compiler, educational vault, games), manually managing which AGENTS.md file to load becomes tedious and error-prone.
ARF Solution: Auto-discovery + keyword-based routing + single command maintenance
System Architecture
~/AGENTS.md (Root Router)
ββ Auto-generated routing table
ββ Scans ~/Code/github.com/theslyprofessor/
ββ Discovers all nested AGENTS.md files
ββ Routes based on keyword matching
~/Code/github.com/theslyprofessor/
ββ PhD/AGENTS.md (dissertation context)
ββ nnt/AGENTS.md (compiler context)
ββ nnt-docs/AGENTS.md (React components context)
ββ midimaze/AGENTS.md (vault management context)
β ββ Audio Discovery/AGENTS.md (song analysis)
β ββ _Nakul/
β ββ 3. SWC Actions/AGENTS.md (teaching)
β ββ 5. Coding Actions/AGENTS.md (development)
β ββ NNT Ecosystem/AGENTS.md (notation tools)
β ββ Obsidian/AGENTS.md (vault workflows)
β ββ Websites/AGENTS.md (web projects)
ββ plant-id-game/AGENTS.md (game context)
How It Works
1. Auto-Discovery
The ~/arf-update script recursively scans your project directories:
bash~/arf-update
What it does:
- Finds all
AGENTS.mdfiles in~/Code/github.com/theslyprofessor/ - Extracts metadata from each file:
- YAML frontmatter
- First H1 heading (title)
- Purpose/description section
- Infers keywords from:
- Directory path components
- File title words
- Description content
2. Keyword Generation
Keywords are algorithmically extracted, not manually assigned:
Example: ~/Code/github.com/theslyprofessor/nnt/AGENTS.md
- Path keywords:
nnt,compiler,coding - Title: "AGENTS.md - nnt Compiler Repository Guidelines"
- Keywords extracted:
nnt,compiler,repository,guidelines - Final keywords (top 5):
coding,compiler,nnt
3. Routing Table Generation
ARF builds a markdown table in ~/AGENTS.md:
markdown| If user asks about... | Load this context | |-----------------------|-------------------| | coding, compiler, nnt | `~/Code/.../nnt/AGENTS.md` | | coding, dissertation, phd | `~/Code/.../PhD/AGENTS.md` | | content, educational, vault | `~/Code/.../midimaze/AGENTS.md` |
4. Context Loading
When you (or OpenCode) work on a task:
User: "Help me debug the NNT compiler's parser"
OpenCode: Matches keywords nnt, compiler β Loads nnt/AGENTS.md
Result: Agent has compiler-specific context (TypeScript, Bun, peggy grammar, etc.)
User: "Create an article about reverb plugins"
OpenCode: No specific keywords β Uses default β Loads midimaze/AGENTS.md
Result: Agent has vault rules, frontmatter templates, article structure patterns
Installation & Setup
1. Create Root Router
Create ~/AGENTS.md with router structure:
markdown--- created: YYYY-MM-DDTHH:MM:SS-TZ updated: YYYY-MM-DDTHH:MM:SS-TZ slug: user-level-router template_type: agent --- # AGENTS.md - User-Level Router ## Agent Context Loading (Router) **Default:** If nothing specified β Load `midimaze/AGENTS.md` **Table Auto-Generated:** Run `~/arf-update` after adding new AGENTS.md files | If user asks about... | Load this context | |-----------------------|-------------------| | (table will be auto-generated) | ## ARF Maintenance Run `~/arf-update` to regenerate routing table when: - Adding new project with AGENTS.md - Renaming project directories - Restructuring code organization
2. Install arf-update Script
Create ~/arf-update:
python#!/usr/bin/env python3 """ ARF Update Script - Auto-generate routing table for AGENTS.md Scans all AGENTS.md files and creates dynamic routing table """ import os import re import sys from pathlib import Path from datetime import datetime import yaml def extract_frontmatter(content): """Extract YAML frontmatter from markdown""" match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL) if match: try: return yaml.safe_load(match.group(1)) except Exception as e: print(f"Warning: Failed to parse frontmatter: {e}", file=sys.stderr) return {} return {} def extract_title(content): """Extract first H1 heading""" match = re.search(r'^#\s+(.+)$', content, re.MULTILINE) return match.group(1).strip() if match else "Unknown" def infer_keywords(file_path, title): """Infer keywords from path and title""" keywords = set() # Extract from path path_parts = str(file_path).lower().split('/') keywords.update(part for part in path_parts if part not in ['code', 'github.com', 'theslyprofessor', 'agents.md', '_nakul']) # Extract from title title_words = re.findall(r'\b[a-z]{4,}\b', title.lower()) keywords.update(w for w in title_words if w not in ['agents', 'agent', 'guidelines', 'context', 'repository']) return sorted(list(keywords)[:8]) def scan_agents_files(base_path): """Scan for all AGENTS.md files and extract metadata""" agents_files = [] base_path = Path(base_path).expanduser() for agents_file in sorted(base_path.rglob("AGENTS.md")): try: content = agents_file.read_text() title = extract_title(content) rel_path = agents_file.relative_to(Path.home()) keywords = infer_keywords(rel_path, title) agents_files.append({ 'path': f"~/{rel_path}", 'keywords': keywords }) except Exception as e: print(f"Warning: Failed to process {agents_file}: {e}", file=sys.stderr) return agents_files def generate_routing_table(agents_files): """Generate markdown routing table""" agents_files.sort(key=lambda x: x['path']) table = [] table.append("| If user asks about... | Load this context |") table.append("|-----------------------|-------------------|") for agent in agents_files: if agent['path'] == "~/AGENTS.md": continue # Skip root router keywords_str = ", ".join(agent['keywords'][:5]) if agent['keywords'] else "general" table.append(f"| {keywords_str} | `{agent['path']}` |") return "\n".join(table) def update_root_agents_md(agents_files, root_path): """Update root AGENTS.md with new routing table""" root_file = Path(root_path).expanduser() if not root_file.exists(): print(f"Error: {root_file} not found", file=sys.stderr) return False content = root_file.read_text() new_table = generate_routing_table(agents_files) # Replace table between router header and next section pattern = r'(## Agent Context Loading \(Router\).*?\n\n\*\*Default:\*\*.*?\n\n)(.*?)(\n\n##)' def replacer(match): return match.group(1) + new_table + match.group(3) updated_content, count = re.subn(pattern, replacer, content, flags=re.DOTALL) if count == 0: print("Warning: Could not find routing table section", file=sys.stderr) return False # Update timestamp updated_content = re.sub( r'updated: .*', f'updated: {datetime.now().strftime("%Y-%m-%dT%H:%M:%S%z")}', updated_content ) root_file.write_text(updated_content) print(f"β Updated {root_file}") print(f"β Added {len(agents_files)-1} agent contexts to routing table") return True def main(): print("ARF Update - Scanning for AGENTS.md files...") print() base_path = "~/Code/github.com/theslyprofessor" agents_files = scan_agents_files(base_path) print(f"Found {len(agents_files)} AGENTS.md files") print() root_path = "~/AGENTS.md" success = update_root_agents_md(agents_files, root_path) if success: print() print("β ARF routing table updated successfully") else: print() print("β Failed to update routing table") sys.exit(1) if __name__ == "__main__": main()
Make executable:
bashchmod +x ~/arf-update
3. Create Project AGENTS.md Files
For each project, create an AGENTS.md file:
yaml--- created: YYYY-MM-DDTHH:MM:SS-TZ updated: YYYY-MM-DDTHH:MM:SS-TZ slug: project-slug template_type: agent --- # AGENTS.md - Project Name ## Purpose Brief description of what this project is and what the AI should know. ## Tech Stack - Languages - Frameworks - Tools ## Project Structure
src/ βββ components/ βββ utils/ βββ tests/
## Coding Standards
[Project-specific guidelines]
4. Run Discovery
bash~/arf-update
Expected output:
ARF Update - Scanning for AGENTS.md files...
Found 14 AGENTS.md files
β Updated /Users/you/AGENTS.md
β Added 13 agent contexts to routing table
β ARF routing table updated successfully
Usage Patterns
Adding New Project
- Create project with AGENTS.md:
bashcd ~/Code/github.com/theslyprofessor/my-new-project touch AGENTS.md # Edit AGENTS.md with project context
- Register with ARF:
bash~/arf-update
- Verify registration:
bashgrep "my-new-project" ~/AGENTS.md
Output:
| my-new-project, [keywords] | `~/Code/.../my-new-project/AGENTS.md` |
Renaming Project Directory
bashmv ~/Code/github.com/theslyprofessor/old-name ~/Code/github.com/theslyprofessor/new-name ~/arf-update
ARF automatically updates paths in routing table.
Maintenance Schedule
Run ~/arf-update when:
- β Adding new project
- β Renaming directories
- β Restructuring code organization
- β Keywords seem stale
- β Quarterly maintenance check
Don't need to run when:
- β Editing existing AGENTS.md content (paths unchanged)
- β Adding files to projects (AGENTS.md location unchanged)
- β Regular coding work
Benefits Over Monolithic AGENTS.md
Scalability
Monolithic: One 5000-line AGENTS.md file
- Hard to navigate
- Context overload for AI
- Slow to parse
- Merge conflicts in teams
ARF: 14 focused AGENTS.md files (200-700 lines each)
- Easy to navigate
- Relevant context only
- Fast loading
- Independent updates
Modularity
Monolithic: All projects in one file
markdown# AGENTS.md ## PhD Dissertation [300 lines] ## NNT Compiler [400 lines] ## Midimaze Vault [500 lines] ...
ARF: Separate files per project
PhD/AGENTS.md (300 lines, LaTeX-specific)
nnt/AGENTS.md (400 lines, TypeScript-specific)
midimaze/AGENTS.md (500 lines, Obsidian-specific)
Maintenance
Monolithic:
- Manual routing decisions
- Outdated sections
- No validation
ARF:
- Automatic discovery
- Always current (run script)
- Built-in validation
Context Efficiency
Monolithic: AI loads 5000 lines every time
- 90% irrelevant to current task
- Token waste
- Slower responses
ARF: AI loads ~300 relevant lines
- 100% relevant to current task
- Efficient token usage
- Faster responses
Real-World Example
Before ARF
markdown# ~/AGENTS.md (5000 lines) ## PhD Dissertation (LaTeX, BibTeX, academic writing) ## NNT Compiler (TypeScript, Bun, peggy grammar) ## Midimaze Vault (Obsidian, frontmatter, educational content) ## Audio Discovery (song analysis, tagging) ## SWC Teaching (Canvas LMS, gradebook) ## Personal Websites (React, Next.js, deployment) ...
Issue: Working on PhD dissertation loads 4700 irrelevant lines about compilers, Obsidian, Canvas, etc.
After ARF
bash~/AGENTS.md (150 lines - just routing) PhD/AGENTS.md (300 lines - LaTeX, academic) nnt/AGENTS.md (400 lines - TypeScript, grammar) midimaze/AGENTS.md (500 lines - Obsidian, vault) ...
Result: Working on PhD loads only 300 relevant LaTeX/academic lines.
Context efficiency: 94% improvement (300 vs 5000 lines)
Advanced Features
Nested Routing
Projects can have their own sub-routers:
midimaze/AGENTS.md (vault router)
ββ Routes to Audio Discovery/AGENTS.md (song analysis)
ββ Routes to _Nakul/3. SWC Actions/AGENTS.md (teaching)
ββ Routes to _Nakul/5. Coding Actions/AGENTS.md (development)
ββ Routes to NNT Ecosystem/AGENTS.md
ββ Routes to Obsidian/AGENTS.md
ββ Routes to Websites/AGENTS.md
Each level has specialized context for progressively specific tasks.
Default Routing
Configure most-common task as default:
markdown**Default:** If nothing specified β Load `midimaze/AGENTS.md`
Result: Simple requests ("ma reverb article") automatically get vault context without explicit routing.
Keyword Customization
Override auto-generated keywords in frontmatter:
yaml--- keywords: [custom, keywords, here] ---
ARF will prefer explicit keywords over inferred ones.
Integration with OpenCode
OpenCode automatically reads ~/AGENTS.md at session start:
- User: "Help with NNT compiler"
- OpenCode: Reads
~/AGENTS.mdrouting table - Match: Keywords
nnt,compilerβnnt/AGENTS.md - OpenCode: Loads
~/Code/.../nnt/AGENTS.md - Context: TypeScript, Bun, peggy, NNT-specific guidelines
- Result: Accurate, context-aware assistance
No user intervention required - routing is transparent.
Troubleshooting
Script Not Found
bashchmod +x ~/arf-update
PyYAML Not Installed
ARF works without PyYAML (uses basic parsing). To install:
bashpip3 install pyyaml
Routing Table Not Updating
Check pattern match in ~/AGENTS.md:
markdown## Agent Context Loading (Router) **Default:** ... | If user asks about... | Load this context | |-----------------------|-------------------|
Pattern must match exactly for replacement to work.
Keywords Not Matching
Run with custom keywords in AGENTS.md frontmatter:
yaml--- keywords: [exact, keywords, you, want] ---
Future Enhancements
Potential Features
- Fuzzy keyword matching - Handle typos, synonyms
- Usage analytics - Track which contexts load most
- Git hooks integration - Auto-run on commit
- JSON export - Machine-readable routing
- Web dashboard - Visual routing map
- Multi-user routing - Team-specific contexts
Community Extensions
ARF is extensible. You could build:
- Language-specific routers (Python projects β python-specific AGENTS.md)
- Framework routers (React projects β react-patterns AGENTS.md)
- Tool-integrated routing (IDE plugins, CLI tools)
Related Concepts
- Context Strategies for AI Coding Agents - Static vs dynamic context
- Context Files for AI Projects - AGENTS.md fundamentals
- OpenCode - CLI interface using ARF routing
- Pattern-Driven Knowledge Bases with AI Assistance - Template systems
Conclusion
ARF solves the scaling problem of AI coding agent context management. Instead of a monolithic AGENTS.md file that becomes unmaintainable, ARF provides:
β
Automatic discovery of project contexts
β
Keyword-based routing to relevant files
β
Single-command maintenance (~/arf-update)
β
Modular, scalable architecture
β
Context efficiency (load only what's needed)
As your codebase grows across multiple repositories, ARF keeps AI assistance accurate and efficient without manual routing overhead.
Next Steps:
- Create
~/AGENTS.mdroot router - Install
~/arf-updatescript - Add AGENTS.md to each project
- Run
~/arf-update - Test with OpenCode: "Help with [project]"
ARF makes multi-project AI assistance practical at scale.