AGENTS.md
Operating rules for anyone β human or AI β working on justapi Runtime.
Read this before touching code. If you are an AI agent resuming after a
context reset, read this file andPLAN.mdfirst, in that order.
1. The one rule that overrides everything else
Do not begin a phase in PLAN.md until the previous phase's exit criteria
are checked off there. If you're unsure whether a gate passed, checkBENCHMARKS.md and CI history β don't assume.
2. Rust-first implementation mandate
If a feature can be implemented in Rust, it must be implemented in Rust β not in the
Python package. Python is reserved for application-facing glue and user callbacks only.
This is the runtime's core performance thesis (see DECISIONS.md ADR-008: "Rust owns I/O and
scheduling, Python owns application logic"). Concretely, the following belong in Rust and must
not be re-implemented under crates/justapi-py/python/justapi/:
- Networking, sockets, TLS, connection management.
- HTTP/protocol parsing and response writing.
- Routing, middleware chaining, rate-limiting, auth/JWT/OAuth2 validation.
- Scheduling, worker/thread pools, background-task execution, concurrency primitives.
- (De)serialization of framework data (encoding bodies/responses for the framework, not user
callbacks). - Hot paths: parsing, validation, buffering, compression.
Python in the framework package is acceptable only for:
- Thin PyO3 re-exports / binding glue (
from ._justapi import X). - Translating between Rust values and Python callables (e.g. invoking a user route/handler).
- User-facing helpers that are not on a hot path and have no Rust equivalent.
Before adding Python logic to the framework, ask: "Could this live in justapi-core /justapi-py Rust instead?" If yes, put it in Rust.
3. Roles
Even in single-agent execution, work through these lenses in sequence for
any non-trivial change β they catch different classes of mistakes:
- Core Runtime β networking, protocol, memory, scheduler correctness and
safety (justapi-core). - Python Bindings β PyO3 boundary, GIL/free-threading correctness, the
native API (justapi-py). - Protocol/Security β TLS, auth, JWT, OAuth2/OIDC, request validation,
SAST scanning, fuzzing, anything parsing untrusted input.
Every change here needs a fuzz target or an explanation of why not. - Data & Validation β Pydantic-style schemas, DB ORM integration,
serialization, type-safe request/response contracts, background tasks. - Resilience β circuit breakers, graceful degradation, retry policies,
rate-limit backpressure, connection pooling. - QA/Benchmark β owns
BENCHMARKS.md, the CI regression gate, and
calling out unqualified performance claims. Target: beat FastAPI on every
benchmark. - Platform/DX β CLI, hot reload, OpenAPI generation, Docker/K8s tooling,
multi-cloud deployment,skills/directory upkeep. - Observability β distributed tracing (OTel), structured logging, metric
dashboards, health checks, alerting integration.
4. Conventions
- Commits:
<emoji> <phase>: <what changed>e.g.π¦ p3: add per-request arena allocator. One logical change per commit. - Commit size: Keep each commit under 100 lines of diff (
git diff --cached --stat). If a file is over 100 lines, split it into smaller
files (types.rs,message.rs,state.rsinstead of a singlemod.rs). Usegit add -pto stage partial hunks if needed.
Exceptions: Cargo.lock (auto-generated) and single cohesive files at
~140 lines max. - Branches:
phase-N/<short-description>. unsafecode: every block needs a// SAFETY:comment explaining the
invariant that makes it sound, and a test that would fail if the invariant
were violated where feasible.- New dependency: justify it in
DECISIONS.mdβ what it replaces or
enables, why the alternative (usually: writing it yourself) is worse. - Public API changes: rustdoc/docstrings required before merge, not after.
- Error handling: use
anyhow::Resultin application code (CLI, bench);
use typed errors (thiserror) in library crates (justapi-core,justapi-py) for errors that cross crate boundaries.
5. Before opening a PR / calling a phase done
- No feature that could be Rust was added in Python (see Β§2); new framework
Python is glue only - Tests pass (
cargo test --workspace) -
cargo clippy --workspace --tests -- -D warningsclean (includes test code) -
cargo fmt --checkclean -
bash scripts/sanitize.shclean (if core touched) β ASan on the full core
suite + a targeted Miri run on the onlyunsafemodule (memory.rs).
This replaces the full-suitecargo mirirun (interpreted = 20+ min for
mostly-safe code; sanitizers run at near-native speed). - Benchmarks run, numbers appended to
BENCHMARKS.md(not overwritten) - No p99 regression >5% vs. previous phase without a
DECISIONS.mdentry -
PLAN.mdupdated: phase status, next steps - New recurring pattern or gotcha? Add/update a
skills/*/SKILL.md
6. Resuming work after a context reset
- Read
PLAN.mdβ find the current phase and its status. - Read the most recent
DECISIONS.mdentries for context on why things are
the way they are. - Skim relevant
skills/*/SKILL.mdfiles for the area you're touching. - Check
BENCHMARKS.mdfor the last recorded numbers so you know the bar. - Continue from where
PLAN.mdsays to continue β don't restart planning
from scratch.
7. When something in the master prompt seems wrong
It might be. If a requirement conflicts with something you've learned during
implementation (e.g., a benchmark shows a "required" custom scheduler isn't
needed, or a crate assumption in the master prompt is stale), write the
conflict and your recommendation into DECISIONS.md and proceed with the
better-informed choice. Don't silently deviate, and don't blindly follow a
now-wrong instruction either.
8. Architecture quick reference
justapi/
Cargo.toml # workspace root
crates/
justapi-core/ # networking, protocol, scheduler, memory
justapi-py/ # PyO3 bindings, native API
justapi-cli/ # `justapi` CLI binary
justapi-bench/ # internal benchmark harness
python/
justapi/ # pip-installable Python package (maturin-built)
skills/ # reusable knowledge modules
benchmarks/ # workload scripts for baseline comparisons
AGENTS.md # this file
PLAN.md # living roadmap (single source of truth)
DECISIONS.md # append-only ADR log
BENCHMARKS.md # append-only results ledger
PROMPT.md # master engineering prompt (reference only)
Request pipeline (target shape)
Kernel β epoll/io_uring β Connection Manager β tokio task
β TLS (rustls) β HTTP parse (hyper) β Router (matchit)
β Middleware chain (Rust: auth/CORS/rate-limit/compression)
β Python boundary (typed, zero-copy request view via PyO3 buffer protocol)
β Application code (native handler)
β Rust serializer (serde_json/simd-json)
β Response write β Socket
Crate dependency graph
justapi-cli β justapi-core
justapi-py β justapi-core
justapi-bench β justapi-core
9. Key skills to consult
| Area | Skill file |
|---|---|
| PyO3 / GIL / unsafe at the FFI boundary | skills/rust-ffi-safety/SKILL.md |
| Running & interpreting benchmarks | skills/benchmark-harness/SKILL.md |
Add new skills as patterns emerge. A good skill saves the next session from
rediscovering a non-obvious invariant or workflow.