Methodology Primer¶
How we build software at Calliope AI. This applies to all repos in the ecosystem.
Knowledge System¶
Every repo has a structured knowledge graph that agents and humans read before working.
File schema¶
bootstrap.md # canonical technical reference — architecture, models, commands, naming
memory.md # persistent decisions, milestones, open questions, project state
CLAUDE.md # Claude Code shim → points to bootstrap.md + memory.md
agents.md # generic agents shim (Codex, etc.)
gemini.md # Gemini CLI shim
calliope.md # internal-only shim (gitignored — auth wiring, env vars, internal URLs)
docs/wiki/ # deep technical docs (architecture, API, policies, compliance, SDK, deployment)
docs/primer.md # this file — methodology and practices
Rules¶
- Write once. All knowledge goes in
bootstrap.mdandmemory.md. Agent shims are thin pointers — never duplicate content. - In-repo only. No external note-taking systems, no Claude auto-memory for project knowledge. The repo is the source of truth.
calliope.mdis always gitignored. Internal wiring (auth, env vars, internal URLs) never in public repos.- Update on change. When you change models, API surfaces, evaluators, or architecture — update
bootstrap.mdin the same commit. memory.mdis append-friendly. Add milestone progress, decisions, open questions. Don't delete history.
What goes where¶
| Content | File |
|---|---|
| Architecture, models, commands, naming conventions | bootstrap.md |
| "Why" decisions, milestone progress, open questions | memory.md |
| API reference, deep dives | docs/wiki/*.md |
| This methodology | docs/primer.md |
| Issue-level work | GitHub Issues |
Issue Workflow¶
- Move to In Progress when you start working on an issue
- Update with progress notes on non-trivial tasks
- Close when committed and verified
- File tickets for bugs found during other work — don't silently fix unrelated things
Issues live at: https://github.com/calliopeai/zentinelle/issues Project board: https://github.com/orgs/calliopeai/projects/4
Git Practices¶
- No co-authorship messages in commits. Ever.
- No rebasing. No force-push.
- Commit directly to
main. - Don't push unless explicitly asked.
- Submodule push order: always push submodules before parent repo.
- Commit messages: imperative mood, explain the "why" not the "what". One-liner for small changes, multi-line for significant ones.
Pre-Commit Checklist (Backend)¶
Run in order. Stop and fix if any step fails.
# 1. Django startup — catches schema ordering violations and import errors
cd backend && pipenv run python -c \
"import django, os; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings'); django.setup()"
# 2. Migration check
pipenv run python manage.py makemigrations --check --dry-run
# 3. Tests
pipenv run pytest
# 4. Lint
pipenv run ruff check
pipenv run isort --check-only .
Multi-Agent Development¶
We develop with multiple AI coding agents simultaneously. Each agent registers with Zentinelle and is governed by the same policies.
Agent integration patterns¶
| Agent | Integration | How it connects |
|---|---|---|
| Claude Code | Hooks (PreToolUse/PostToolUse) | Calls /evaluate before tool calls, /events after |
| Codex (OpenAI) | LLM Proxy | OPENAI_BASE_URL → local proxy → Zentinelle → OpenAI |
| Gemini | Hooks (native) or LLM Proxy | install-gemini for hooks, or GOOGLE_GEMINI_BASE_URL → proxy |
| Custom agents | REST API or Proxy | Call /evaluate directly or route through proxy |
SDK¶
Package: zentinelle-agent (in zentinelle-sdk.git/plugins/agent/)
zentinelle-agent install # Claude Code hooks
zentinelle-agent proxy # Local proxy (--provider anthropic|openai|google)
zentinelle-agent status # Show current state
Policy-Driven Development¶
All agent activity goes through the policy engine. Policies are the primary governance mechanism.
Policy types that matter during development¶
| Policy | What it catches | Enforcement |
|---|---|---|
rate_limit |
Request rate, token budget | enforce |
tool_permission |
Deny dangerous tools, require approval | enforce |
model_restriction |
Only approved models/providers | enforce |
agent_capability |
Action-level RBAC | audit or enforce |
network_policy |
Block risky domains | enforce |
Enforcement modes¶
- enforce — blocks the action, agent sees the reason
- audit — logs the violation, doesn't block
- disabled — policy exists but doesn't evaluate
Cache behavior¶
Policy changes take effect immediately (versioned cache keys). No 5-minute delay.
Monitoring¶
The GRC portal at /zentinelle/monitoring/ shows live agent activity:
- Live Activity tab — every tool call and LLM invocation, with endpoint, model, tokens, latency
- Content Scanner — PII detection, content moderation
- Anomalies — usage spikes, repeat violations
- Compliance Alerts — drift detection, policy health checks
Data flows:
Hook (PreToolUse) → /evaluate → PolicyEngine → Event + InteractionLog
Hook (PostToolUse) → /events → Event
Proxy → PolicyEngine → upstream → InteractionLog
Timestamps¶
- Backend: all
DateTimeFieldvalues stored in UTC (DjangoUSE_TZ=True) - Frontend: display conversion happens in the browser based on user timezone preference
- Logs/events: always include timezone context when displaying to users
Documentation Site¶
- Domain:
zentinelle.dev(GitHub Pages) - Source:
docs/directory - Includes: primer, wiki, API reference, SDK guide
What Not To Do¶
- Don't keep project notes outside the repo (no Notion, no Claude auto-memory for project state)
- Don't hardcode agent types, model lists, or provider URLs in the frontend — pull from the backend
- Don't create
InteractionLogandEventfor the same thing separately — wire them at the source - Don't skip the pre-commit checklist
- Don't silently fix bugs found during other work — file a ticket
- Don't rebase or force-push