11 KiB
Migration Guide: Hash-Based Architecture
Date: 2026-02-17
Breaking Change: Yes
Affects: All users with existing sessions
What Changed
Agent Orchestrator has migrated from flat, configurable directories (dataDir and worktreeDir) to a hash-based project isolation architecture. This change eliminates configuration overhead and prevents collisions when running multiple orchestrator instances from different directories.
Before (Flat Architecture)
# agent-orchestrator.yaml
dataDir: ~/.ao-sessions
worktreeDir: ~/.ao-worktrees
projects:
my-app:
path: ~/repos/my-app
Problems:
- Multiple configs sharing same
dataDircaused session collisions - Manual path configuration required
- No isolation between orchestrator instances
- Backwards compatibility code added complexity
After (Hash-Based Architecture)
# agent-orchestrator.yaml
# No dataDir or worktreeDir needed!
projects:
my-app:
path: ~/repos/my-app
Benefits:
- Zero configuration — paths auto-derived from config location
- Complete isolation — each config gets unique namespace
- Collision-free — SHA256 hash prevents conflicts
- Clean codebase — no backwards compatibility code
Architecture Details
Directory Structure
All orchestrator data now lives under ~/.agent-orchestrator/:
~/.agent-orchestrator/
├── {hash}-{projectId}/ # Unique per config+project
│ ├── .origin # Stores config path (collision detection)
│ ├── sessions/ # Session metadata
│ │ ├── int-1 # Metadata for session int-1
│ │ ├── int-2
│ │ └── archive/ # Archived metadata
│ └── worktrees/ # Git worktrees
│ ├── int-1/ # Worktree for session int-1
│ └── int-2/
Hash Generation
The hash is the first 12 characters of SHA256(realpath(dirname(configPath))):
// Config at: ~/projects/acme/agent-orchestrator.yaml
// Hash of: /Users/you/projects/acme
// Result: a3b4c5d6e7f8
// Final path: ~/.agent-orchestrator/a3b4c5d6e7f8-my-app/
Why 12 chars? Balance between uniqueness (collision probability ~1 in 16 billion) and path length.
Session Naming Layers
Three levels of naming for compatibility:
- User-facing:
int-1,ao-42(short, clean) - Tmux:
a3b4c5d6e7f8-int-1(globally unique across all configs) - Metadata file:
int-1(within project-specificsessions/directory)
Breaking Changes
1. Config File Changes
REMOVED fields (will cause validation errors if present):
dataDirworktreeDir
REQUIRED field:
configPath(automatically set byloadConfig())
Migration:
# agent-orchestrator.yaml
- dataDir: ~/.ao-sessions
- worktreeDir: ~/.ao-worktrees
projects:
my-app:
path: ~/repos/my-app
2. Metadata File Locations
Before:
~/.ao-sessions/
├── int-1 # Flat directory, all projects mixed
├── int-2
├── ao-1
└── ao-2
After:
~/.agent-orchestrator/
├── a3b4c5d6e7f8-integrator/sessions/
│ ├── int-1 # Integrator project sessions
│ └── int-2
└── f9e8d7c6b5a4-my-app/sessions/
├── ao-1 # My-app project sessions
└── ao-2
Impact: Existing metadata files will not be automatically migrated. See migration steps below.
3. Worktree Locations
Before:
~/.ao-worktrees/
├── integrator/
│ ├── int-1
│ └── int-2
└── my-app/
├── ao-1
└── ao-2
After:
~/.agent-orchestrator/
├── a3b4c5d6e7f8-integrator/worktrees/
│ ├── int-1
│ └── int-2
└── f9e8d7c6b5a4-my-app/worktrees/
├── ao-1
└── ao-2
Impact: Existing worktrees will not be automatically migrated. Git will report them as "missing" and they must be manually removed.
4. Environment Variables
Before:
AO_DATA_DIR=~/.ao-sessions # Flat path
After:
AO_DATA_DIR=~/.agent-orchestrator/a3b4c5d6e7f8-integrator/sessions/
Impact: Scripts or hooks relying on AO_DATA_DIR pointing to a flat directory will break.
5. API Changes (For Plugin Developers)
Removed from OrchestratorConfig:
interface OrchestratorConfig {
dataDir: string; // REMOVED
worktreeDir: string; // REMOVED
configPath: string; // NOW REQUIRED
}
New Path Utilities (use these instead):
import {
getSessionsDir,
getWorktreesDir,
getProjectBaseDir,
generateConfigHash,
generateInstanceId,
validateAndStoreOrigin,
} from "@composio/ao-core";
// Calculate paths dynamically
const sessionsDir = getSessionsDir(configPath, projectPath);
const worktreesDir = getWorktreesDir(configPath, projectPath);
Migration Steps
Step 1: Clean Up Config File
Remove dataDir and worktreeDir from your config:
# Edit your agent-orchestrator.yaml
vim ~/path/to/agent-orchestrator.yaml
Remove these lines:
dataDir: ~/.ao-sessions
worktreeDir: ~/.ao-worktrees
Step 2: Kill Existing Sessions
IMPORTANT: Existing sessions will not automatically migrate. You must kill them first.
# List all tmux sessions
tmux ls
# Kill all orchestrator sessions (adjust prefix as needed)
tmux ls | grep -E '^(int|ao|app)-[0-9]+:' | cut -d: -f1 | xargs -I{} tmux kill-session -t {}
# Or kill all tmux sessions (nuclear option)
tmux kill-server
Step 3: Clean Up Old Directories
Worktrees must be removed from git:
# For each project, remove old worktrees
cd ~/repos/integrator
# List worktrees
git worktree list
# Remove each old worktree
git worktree remove ~/.ao-worktrees/integrator/int-1 --force
git worktree remove ~/.ao-worktrees/integrator/int-2 --force
# ... repeat for all
# Prune stale references
git worktree prune
Metadata can be archived for reference:
# Archive old metadata (optional)
mv ~/.ao-sessions ~/.ao-sessions-backup-$(date +%Y%m%d)
# Or delete if you don't need it
rm -rf ~/.ao-sessions
Worktree directory can be removed after cleaning up git references:
# Remove old worktree directory (after git worktree remove)
rm -rf ~/.ao-worktrees
Step 4: Update to Latest Version
# Pull latest code
git pull origin main
# Reinstall dependencies
pnpm install
# Rebuild packages
pnpm build
Step 5: Start Fresh
# Start orchestrator (creates new directory structure)
ao start
# Spawn new sessions (uses hash-based paths)
ao spawn my-app INT-1234
Step 6: Verify New Structure
# Check that new directories were created
ls -la ~/.agent-orchestrator/
# You should see directories like:
# a3b4c5d6e7f8-my-app/
# .origin
# sessions/
# worktrees/
# Check tmux sessions have hash prefix
tmux ls
# Should show: a3b4c5d6e7f8-int-1, a3b4c5d6e7f8-int-2, etc.
Rollback (If Needed)
If you need to rollback to the old architecture:
-
Checkout previous commit (before hash-based migration):
git checkout <commit-before-migration> pnpm install pnpm build -
Restore old config:
# Add back to agent-orchestrator.yaml dataDir: ~/.ao-sessions worktreeDir: ~/.ao-worktrees -
Restore old metadata (if archived):
mv ~/.ao-sessions-backup-20260217 ~/.ao-sessions -
Kill new hash-based sessions:
tmux ls | grep -E '^[a-f0-9]{12}-' | cut -d: -f1 | xargs -I{} tmux kill-session -t {}
FAQ
Q: Why can't I use my old sessions?
A: The metadata file structure changed. Old sessions point to flat directories (~/.ao-sessions/int-1) but the new code expects hash-based paths (~/.agent-orchestrator/a3b4c5d6e7f8-integrator/sessions/int-1). You must kill old sessions and spawn new ones.
Q: Will my PRs be lost?
A: No! PRs are on GitHub, not in local sessions. You can:
- Check
gh pr listto see all open PRs - Spawn new sessions for PRs that need work:
ao spawn integrator --branch feat/existing-branch
Q: What about in-progress work?
A: Git worktrees contain your code changes. Before killing sessions:
- Commit or stash changes in each worktree
- Note which issues/branches were being worked on
- After migration, spawn new sessions and continue work
Q: Can I migrate metadata files manually?
A: Yes, but not recommended. The manual process:
# For each project
OLD_DIR=~/.ao-sessions
NEW_DIR=~/.agent-orchestrator/$(python3 -c "import hashlib; print(hashlib.sha256(b'/Users/you/path/to/config/dir').hexdigest()[:12])")-integrator/sessions
mkdir -p "$NEW_DIR"
# Copy metadata files
cp "$OLD_DIR"/int-* "$NEW_DIR/"
# Update worktree paths in each file (required!)
for file in "$NEW_DIR"/*; do
sed -i '' 's|worktree=~/.ao-worktrees/integrator/|worktree=~/.agent-orchestrator/HASH-integrator/worktrees/|g' "$file"
done
This is error-prone. Recommended: Kill old sessions and spawn fresh ones.
Q: What happens if I have multiple config files?
A: Each config gets a unique hash! This is the main benefit of the new architecture:
# Config 1: ~/projects/acme/agent-orchestrator.yaml
# Hash: a3b4c5d6e7f8
# Sessions: ~/.agent-orchestrator/a3b4c5d6e7f8-my-app/
# Config 2: ~/experiments/test/agent-orchestrator.yaml
# Hash: 1f2e3d4c5b6a
# Sessions: ~/.agent-orchestrator/1f2e3d4c5b6a-my-app/
No conflicts, complete isolation!
Q: How do I find the hash for my config?
A:
# Calculate hash for your config directory
echo -n "/path/to/your/config/dir" | sha256sum | cut -c1-12
# Or let ao print it
ao status
# Output shows: Config: /path/to/config.yaml
# Hash will be in directory names: ~/.agent-orchestrator/{hash}-{project}/
Q: What if two configs have the same hash (collision)?
A: The .origin file detects this and throws an error with instructions:
Hash collision detected!
Directory: ~/.agent-orchestrator/a3b4c5d6e7f8-my-app
Expected config: /Users/you/config1/agent-orchestrator.yaml
Actual config: /Users/you/config2/agent-orchestrator.yaml
This is a rare hash collision. Please move one of the configs to a different directory.
Solution: Move one config to a different directory. Collision probability is ~1 in 16 billion with 12-character hashes.
Support
If you encounter issues during migration:
- Check existing sessions:
tmux ls - Check new directory structure:
ls -la ~/.agent-orchestrator/ - Check config validation:
ao status - Review git worktrees:
git worktree list(from project directory) - Check logs:
journalctl -u ao-orchestratoror tmux session output
For bugs or questions, file an issue: https://github.com/composiohq/agent-orchestrator/issues
Summary
Action Required:
- ✅ Remove
dataDirandworktreeDirfrom config - ✅ Kill all existing sessions (
tmux kill-server) - ✅ Clean up old git worktrees (
git worktree remove --force) - ✅ Remove old directories (
~/.ao-sessions,~/.ao-worktrees) - ✅ Update to latest version (
pnpm install && pnpm build) - ✅ Start fresh (
ao start,ao spawn)
Expected Downtime: ~10 minutes (time to kill sessions, clean worktrees, respawn)
Risk Level: Low (PRs are safe, code is in git, only local sessions affected)
Benefit: Cleaner architecture, zero config, collision-free multi-instance support