Claude-powered Python agents with ontology-driven project planning, autonomous code generation, and defense-in-depth security hardening.
The pipeline takes a project from idea to production code through structured ontology exploration, branching solution candidates, and an autonomous coding agent that enforces 10 quality gates before every commit.
AGPL-3.0-or-later. Python 3.11+. Requires the Claude Agent SDK.
A monorepo containing six CLI tools and a shared ontology framework:
| Tool | Mode | Purpose |
|---|---|---|
aofire-discovery-agent |
Interactive | Build a domain ontology through conversation |
aofire-divergence-agent |
Autonomous | Generate N candidate solution architectures |
aofire-convergence-agent |
Interactive | Compare, select, and refine candidates |
aofire-coding-agent |
Autonomous | Write production-quality code with Sonnet/Opus escalation |
aofire-planning-agent |
Interactive | Freeform project design (no ontology) |
aofire-call-graph |
Analysis | Source-to-sink taint analysis with CWE tagging |
Plus shared infrastructure:
| Module | Purpose |
|---|---|
ontology.py |
16 Pydantic models: entities, relationships, modules, DAG |
types.py |
Annotated + Literal shared type definitions |
dag_utils.py |
DAG persistence with HMAC integrity signing |
dag_integrity.py |
HMAC verification + injection pattern scanning |
tool_guard.py |
can_use_tool callback: Bash blocklist + path confinement |
rules.py |
System prompts with frame_data() content framing |
pip install aofire-python-agentFor development (includes test/analysis tools):
git clone https://github.com/edhodapp/python-agent.git
cd python-agent
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"aofire-discovery-agent --> aofire-divergence-agent --> aofire-convergence-agent --> aofire-coding-agent
(interactive) (autonomous) (interactive) (autonomous)
Build domain Generate N Compare, select, Write code to
ontology solution candidates accept, refine production standards
All state is saved to an ontology DAG (a JSON file). Each node is a complete ontology snapshot. Each edge records a design decision. You can backtrack to any prior state and explore a different path.
Build a domain ontology interactively. The agent asks questions about your domain and constructs entities, relationships, and constraints.
aofire-discovery-agent "A URL shortener service" --dag-file shortener.jsonExample session:
Planner: I'll help you design a URL shortener. Who are the users?
> Anyone can follow a link. Registered users create short URLs.
[Agent proposes entities: User, ShortURL, relationship: User owns ShortURL]
> show
Entities (2):
user: User [username, api_key]
short_url: ShortURL [slug, target_url, click_count]
Relationships (1):
user --owns--> short_url (one_to_many)
Open Questions (2):
[open] q1: Storage backend?
[open] q2: Slug format?
> save initial domain model
Saved snapshot: 20260401T120000...
> quit
Commands: show, save [label], back, quit/exit/done
Options:
--dag-file PATH-- DAG JSON file (default:ontology.json)-m MODEL-- model (default:claude-opus-4-6)
Autonomously generate multiple solution candidates. The agent identifies key architectural decision points, then generates one complete solution per strategy.
aofire-divergence-agent --dag-file shortener.json -n 3Identifying 3 strategies...
Generating candidate: monolith-sqlite...
Created: monolith-sqlite
Generating candidate: microservices-postgres...
Created: microservices-postgres
Generating candidate: serverless-dynamo...
Created: serverless-dynamo
Done. 3 candidates. Cost: $0.1234
Each candidate fills in the solution domain: modules, classes, functions, data models, external dependencies, and test strategies. The DAG now has three branching children.
Options:
--dag-file PATH-- DAG JSON file (required)-n N-- number of candidates (default: 3)-m MODEL-- model (default:claude-sonnet-4-6)--max-budget USD-- spending cap (default: 5.0)
Compare candidates, select one, and refine it interactively. The LLM has context of all candidates and assists with comparisons.
aofire-convergence-agent --dag-file shortener.json> list
1. monolith-sqlite: Entities (2), Modules (4)...
2. microservices-postgres: Entities (2), Modules (6)...
3. serverless-dynamo: Entities (2), Modules (5)...
> compare monolith-sqlite and microservices-postgres on complexity
[LLM explains trade-offs between the two approaches]
> select 1
Selected: monolith-sqlite
> show
[Full ontology: entities, relationships, modules with classes/functions]
> accept
Accepted: monolith-sqlite. You can now refine.
> Add rate limiting to the API module
[LLM proposes ontology update with new RateLimiter class]
> save final design
> quit
Commands: list, select <n>, back, show, accept, save [label].
Any other text goes to the LLM (e.g., "compare", "explain", "refine").
Options:
--dag-file PATH-- DAG JSON file (required)-m MODEL-- model (default:claude-opus-4-6)
The coding agent writes code, runs all quality checks, and iterates until everything passes. Starts with Sonnet for cost efficiency; automatically escalates to Opus if it gets stuck.
aofire-coding-agent "Implement the URL shortener from the accepted design" -d ./shortener --dag-file shortener.jsonPass --dag-file to give the coding agent the ontology as structured design
context. The agent sees entities, module specs, function signatures, and test
strategies from the accepted design.
The agent's workflow (11 steps):
- Read existing code
- Write/modify code
- flake8 (complexity <= 5)
- mypy --strict
- pytest (100% branch coverage)
- Iterate on failures
- mutmut (100% kill rate)
- Fuzz tests for external-input functions
- aofire-call-graph taint analysis
- Functional test gap analysis
- Commit
If the agent can't fix an issue (e.g., needs a # type: ignore), it
presents grouped findings for user approval rather than silently
suppressing.
Options:
-d DIR-- project directory (default:.)-m MODEL-- initial model (default:claude-sonnet-4-6)--max-turns N-- step limit (default: 30)--max-budget USD-- spending cap (default: 5.0)--dag-file PATH-- ontology DAG JSON file for design context (optional)
Re-run convergence on the same DAG to navigate back and try a different branch. All intermediate states are preserved:
aofire-convergence-agent --dag-file shortener.json
> back
> select 2
> acceptFor freeform project design without the ontology pipeline:
aofire-planning-agent "A CLI tool that converts CSV to JSON with schema validation"Uses Opus by default. Produces a structured markdown plan. Type quit to end.
Source-to-sink taint analysis using Python's ast module. Traces data
flow from external inputs through the call graph to dangerous sinks.
Each finding tagged with a CWE code.
aofire-call-graph src/python_agent/ # text report
aofire-call-graph src/python_agent/ --sarif # SARIF JSON for CI
aofire-call-graph src/python_agent/ --include-sanitized # show all pathsSources detected: input(), json.loads, open(), .model_validate(),
.parse_args(), .query() (SDK responses).
Sinks detected: eval/exec, subprocess/os.system, .write(),
.query() (prompt injection), print() (info exposure).
Suppress acknowledged findings with mandatory comments:
# taint: ignore[CWE-200] -- Interactive agent displays LLM output to user
async def run(description: str, model: str) -> None:Defense-in-depth across all agents:
| Layer | Defense | Protects Against |
|---|---|---|
| 1 | frame_data() content framing |
Prompt injection via embedded data |
| 2 | HMAC-SHA256 DAG integrity | File tampering between sessions |
| 3 | Pydantic BaseModel validation |
Malformed data at construction |
| 4 | can_use_tool callback (tool guard) |
Dangerous Bash commands + path escape |
| 5 | Injection pattern scanner | Common injection phrases in text fields |
| 6 | Framing escape detection | </ontology-data> breakout attempts |
| 7 | Call graph taint analysis | Unguarded source-to-sink data flows |
| 8 | Taint suppressions with mandatory comments | Acknowledged risks with audit trail |
| 9 | User approval workflow | Silent suppression by autonomous agent |
The coding agent's tool guard blocks: curl, wget, ssh, sudo,
rm -rf /, dd, mkfs, chmod 777, chown, pkill, writes to
/etc, ~/.ssh, ~/.bashrc. File operations confined to project
directory.
16 Pydantic models capturing both problem and solution domains:
Problem domain: Entity, Property, PropertyType, Relationship, DomainConstraint
Solution domain: ModuleSpec, ClassSpec, FunctionSpec, DataModel, ExternalDependency
Planning state: OpenQuestion (unresolved decisions)
DAG: DAGNode (ontology snapshots), DAGEdge (design decisions), OntologyDAG (the full versioned graph)
Type constraints enforced via Annotated types: SafeId (alphanumeric,
max 100 chars), ShortName (max 100 chars), Description (max 2000
chars). Enum fields use Literal types: PropertyKind, Cardinality,
ModuleStatus, Priority.
All code produced by these agents (and the agents themselves) meets:
- flake8 clean with
--max-complexity=5 - mypy --strict with zero errors
- 100% branch coverage via pytest (570 tests)
- 100% mutant kill rate via mutmut v2
- Fuzz testing via hypothesis on all external-input functions
- Call graph taint analysis with CWE tagging
- Functional test gap analysis as final verification step
- Prompt injection hardening across all agents
See CLAUDE.md for the complete coding standards.
Version: 0.1.1
What works:
- Full ontology pipeline: discovery, divergence, convergence
- Autonomous coding agent with Sonnet/Opus escalation
- All security hardening layers active
- 570 tests, 14 source files, all quality gates pass
- aofire-call-graph reports clean (no unguarded taint paths)
What's next:
- Wire coding agent to consume ontology nodes as implementation specs
- End-to-end pipeline test (idea to running code)
- CI setup (GitHub Actions)
- Performance requirements as soft ontology constraints (advisory, not blocking)
- Tier 2 hardening: coding agent command audit log by default
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
# Full quality gate
.venv/bin/flake8 --max-complexity=5 src/ tests/
.venv/bin/mypy --strict src/
.venv/bin/pytest --cov --cov-branch --cov-report=term-missing
.venv/bin/mutmut run
.venv/bin/pytest tests/test_fuzz.py --hypothesis-profile=ci
.venv/bin/aofire-call-graph src/python_agent/# Setup (first time)
pip install devpi-server devpi-client
devpi-server --init && devpi-server --start --port 3141
devpi use http://localhost:3141
devpi user -c myuser password=
devpi login myuser
devpi index -c dev bases=root/pypi
devpi use myuser/dev
# Publish
devpi upload
# Install from local index
pip install aofire-python-agent -i http://localhost:3141/myuser/dev/+simple/AGPL-3.0-or-later. See LICENSE.