AI agents that turn Jira tickets into production-ready pull requests. Zero infrastructure — runs entirely on GitHub Actions.
uv sync --all-extras # Install all deps (never use pip)
pytest tests/ -v # Run tests
ruff format . # Format
ruff check . # Lint
python run_agent.py refinement # Run an agent locallyagents/ → Concrete agent definitions (declarative, not algorithmic)
framework/ → Core: BaseAgent, runners, providers, tools, guardrails
providers/ → LLM abstraction (Anthropic, OpenAI, Google)
tools/ → Tool definitions and execution
mcp_server/ → MCP servers for Jira and GitHub integration
core/models.py → Domain models (WorkItem, Spec, Task, etc.)
prompts/ → Agent system prompt templates (.md)
run_agent.py → CLI entry point for all agents
repo-map.json → Jira project → GitHub repo routing config
- Agents are declarative: they define tools, guardrails, and prompts — Claude makes all decisions. No algorithmic control flow inside agents. Exception:
agents/sync.pyis a deterministic, LLM-free PR-state poller (cron-driven, talks to GitHub/Jira REST directly) — there's no judgement for a model to make, so it intentionally isn't aBaseAgent. - Unified tool names: the SDK tool registry (
framework/tools/) and the MCP servers (mcp_server/) expose the SAME tool names (e.g.create_technical_issue), so prompts and guardrails work identically under both runners. Keep them in sync when adding tools. - Provider abstraction: All LLM calls go through
framework/providers/base.py(LLMProvider ABC). Never importanthropic/openai/googledirectly in runners or agents. - Canonical formats:
ToolDef,LLMResponse,CanonicalMessageinframework/providers/base.py— providers convert to/from these. - Two runners:
AgentRunner(CLI viaclaude -p) andSDKRunner(direct API calls). Selected byLLM_PROVIDERenv var (clivsanthropic/openai/google). - MCP for external tools: Jira and GitHub APIs are exposed via MCP servers (
.mcp.json), not called directly by agents. - Guardrails: Post-execution validators in
framework/guardrail.py. Always add guardrails when creating new agents.
- Create
agents/your_agent.py— subclassBaseAgent, declare tools/guardrails - Create
prompts/your-agent.md— system prompt template - Add workflow
.github/workflows/your-agent.yml - Add tests in
tests/ - Register in
run_agent.py
- Create
framework/providers/your_provider.py— implementLLMProviderABC - Implement
complete(),convert_tools(),convert_messages() - Register in
framework/providers/__init__.py(get_providerfactory)
repo-map.json: Maps Jira projects/components → GitHub repos. Supports per-routellm_providerandllm_modeloverrides.LLM_PROVIDERenv var:cli|anthropic|openai|google(optionally with model:anthropic/claude-haiku-4-5-20251001)REPO_MAP_ENGINEenv var:ast(default) |graphify.graphifyinjects the stored Graphify knowledge graph (built by the graphify-onboard/sync workflows) into the agent prompt, falling back to the AST map if no graph is available. Seedocs/graphify-integration-plan.md..mcp.json: MCP server config for Jira and GitHub tools
- Python 3.12+,
uvonly (never pip) - Ruff for formatting and linting (line-length: 100)
- Type hints on all function signatures
- Keep core dependencies minimal: only
httpx,pydantic,mcp - Provider SDKs are optional extras — guard imports accordingly
- pytest with pytest-asyncio (asyncio_mode = "auto")
- Tests live in
tests/ - Mock external calls (Jira, GitHub, LLM APIs) — never hit real services in tests