Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ComposioHQ/agent-orchestrator/llms.txt
Use this file to discover all available pages before exploring further.
Contributions are welcome! The plugin system makes it straightforward to add support for new agents, runtimes, trackers, and notification channels.
Getting Started
Prerequisites
- Node.js 20+
- pnpm 9.15+
- Git 2.30+
First-Time Setup
Clone the repository
git clone https://github.com/ComposioHQ/agent-orchestrator.git
cd agent-orchestrator
Build all packages
Building is required before running the dev server.
Copy example config
cp agent-orchestrator.yaml.example agent-orchestrator.yaml
Configure your settings
$EDITOR agent-orchestrator.yaml
Running the Dev Server
The web dashboard depends on built packages. Always build before running the dev server.
# Build all packages
pnpm build
# Start dev server
cd packages/web
pnpm dev
# Open http://localhost:3000 (or your configured port)
Project Structure
agent-orchestrator/
├── packages/
│ ├── core/ # Core types, services, config
│ ├── cli/ # CLI tool (ao command)
│ ├── web/ # Next.js dashboard
│ ├── plugins/ # All plugins
│ │ ├── runtime-*/ # Runtime plugins (tmux, docker, k8s)
│ │ ├── agent-*/ # Agent adapters (claude-code, codex, aider)
│ │ ├── workspace-*/ # Workspace providers (worktree, clone)
│ │ ├── tracker-*/ # Issue trackers (github, linear)
│ │ ├── scm-github/ # SCM adapter
│ │ ├── notifier-*/ # Notification channels
│ │ └── terminal-*/ # Terminal UIs
│ └── integration-tests/ # Integration tests
├── agent-orchestrator.yaml.example
├── .gitleaks.toml # Secret scanning config
├── .husky/ # Git hooks
└── docs/ # Documentation
Development Workflow
Making Changes
Create a feature branch
git checkout -b feat/your-feature
Make your changes
- Follow CLAUDE.md conventions
- Add tests for new features
- Update documentation
Build and test
pnpm build
pnpm test
pnpm lint
pnpm typecheck
Commit
git add .
git commit -m "feat: add your feature"
Push and open PR
git push origin feat/your-feature
Code Conventions
TypeScript
- ESM modules -
.js extensions in imports
node: prefix for builtins (node:fs, node:path)
- Strict mode enabled
type imports for type-only imports
- No
any - use unknown + type guards
- Semicolons, double quotes, 2-space indent - enforced by Prettier
// Good
import type { Runtime } from "@composio/ao-core";
import { readFileSync } from "node:fs";
import { foo } from "./bar.js";
// Bad
import { Runtime } from "@composio/ao-core"; // Should be type import
import { readFileSync } from "fs"; // Missing node: prefix
import { foo } from "./bar"; // Missing .js extension
Shell Commands
Security critical: Always follow these rules to prevent shell injection vulnerabilities.
- Always use
execFile (or spawn) - NEVER exec
- Always add timeouts -
{ timeout: 30_000 }
- Never interpolate user input - pass as array args
- Do NOT use
JSON.stringify for shell escaping
// GOOD
import { execFile } from "node:child_process";
import { promisify } from "node:util";
const execFileAsync = promisify(execFile);
const { stdout } = await execFileAsync("git", ["branch", "--show-current"], {
timeout: 30_000
});
// BAD - shell injection risk
exec(`git checkout ${branchName}`); // branchName could contain ; rm -rf /
Plugin Development
Every plugin implements one of the core interfaces defined in packages/core/src/types.ts.
Plugin Pattern
import type { PluginModule, Runtime } from "@composio/ao-core";
export const manifest = {
name: "my-plugin",
slot: "runtime" as const,
description: "My plugin",
version: "0.1.0",
};
export function create(): Runtime {
return {
name: "my-plugin",
async create(config) {
/* ... */
},
// ... implement interface
};
}
export default { manifest, create } satisfies PluginModule<Runtime>;
Adding a New Plugin
Create plugin package
mkdir -p packages/plugins/runtime-myplugin
cd packages/plugins/runtime-myplugin
Set up package.json
{
"name": "@composio/ao-runtime-myplugin",
"version": "0.1.0",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"typecheck": "tsc --noEmit",
"test": "vitest"
},
"dependencies": {
"@composio/ao-core": "workspace:*"
}
}
Create src/index.ts
Implement the appropriate interface (Runtime, Agent, Workspace, Tracker, etc.).
Register in core
Add to packages/core/src/services/plugin-registry.ts.
Add tests
Create src/index.test.ts with test cases.
Build and test
pnpm --filter @composio/ao-runtime-myplugin build
pnpm --filter @composio/ao-runtime-myplugin test
Plugin Slots
Eight slots available for plugins:
| Slot | Interface | Default | Examples |
|---|
| Runtime | Runtime | tmux | docker, k8s, process |
| Agent | Agent | claude-code | codex, aider, opencode |
| Workspace | Workspace | worktree | clone |
| Tracker | Tracker | github | linear |
| SCM | SCM | github | — |
| Notifier | Notifier | desktop | slack, composio, webhook |
| Terminal | Terminal | iterm2 | web |
| Lifecycle | (core) | core | — |
All interfaces are defined in packages/core/src/types.ts - read this file first!
Testing
# Run all tests
pnpm test
# Run tests for specific package
pnpm --filter @composio/ao-core test
# Run tests in watch mode
pnpm --filter @composio/ao-core test -- --watch
# Run integration tests
pnpm test:integration
Test Coverage
The project has 3,288 test cases ensuring reliability and correctness.
Security
Secret Scanning
A pre-commit hook automatically scans for secrets:
🔒 Scanning staged files for secrets...
✅ No secrets detected
If secrets are detected:
- Remove the secret from the file
- Use environment variables:
${SECRET_NAME}
- Add to
.env.local (in .gitignore)
- Update example configs with placeholders
What Triggers the Scanner
- API keys:
lin_api_*, ghp_*, gho_*, sk-*, AKIA*
- Tokens:
xoxb-*, xoxa-*, etc.
- Webhooks:
https://hooks.slack.com/*, https://discord.com/api/webhooks/*
- Private keys:
-----BEGIN PRIVATE KEY-----
- Database URLs:
postgres://user:pass@host
- Generic patterns:
api_key=..., token=..., password=...
False Positives
If you get a false positive:
Verify it's not a real secret
Double-check the detected pattern is actually safe.
Update allowlist
Edit .gitleaks.toml:[allowlist]
regexes = [
'''your-pattern-here''',
]
Commit the change
git add .gitleaks.toml
git commit -m "chore: update gitleaks allowlist"
Working with Worktrees
If using git worktrees for parallel development:
# Create worktree
git worktree add ../ao-feature-x feat/feature-x
cd ../ao-feature-x
# Install and build
pnpm install
pnpm build
# Copy config
cp ../agent-orchestrator/agent-orchestrator.yaml .
# Start dev server
cd packages/web
pnpm dev
Debugging
Enable Verbose Logging
Attach to tmux Session
tmux attach -t session-name
# Detach: Ctrl-b d
cat ~/.agent-orchestrator/my-app-3
Check Session Status
curl http://localhost:3000/api/sessions/my-app-3
Submission Guidelines
Pull Request Process
Ensure all tests pass
pnpm build && pnpm test && pnpm lint && pnpm typecheck
Write a clear description
- What does this PR do?
- Why is it needed?
- How does it work?
- Any breaking changes?
Link related issues
Use Fixes #123 or Closes #123 in the PR description.
Request review
Tag relevant maintainers or wait for automatic review assignment.
Use Conventional Commits:
feat: add support for Docker runtime
fix: resolve memory leak in session cleanup
chore: update dependencies
docs: improve plugin development guide
test: add integration tests for Linear tracker
Code Review
Expect feedback on:
- Code quality and style
- Test coverage
- Documentation updates
- Security considerations
- Performance implications
Resources
Getting Help
Need help contributing?
- Check existing issues and discussions
- Review the troubleshooting guide
- Ask questions in GitHub Discussions
- Join the community channels
Thank you for contributing to Agent Orchestrator!