This page is a contributor’s map of Cognis. If you’re adding a new feature, this is where you check that you’re putting it in the right crate and following the existing shape.Documentation Index
Fetch the complete documentation index at: https://cognis.vasanth.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Workspace map
Dependency rules (strict)
These are enforced by the build:cognis-corehas zero internal-crate dependencies.cognis-llm,cognis-rag,cognisgraph,cognis-traceeach depend only oncognis-core(andcognis-macroswhere they use a derive). They do not depend on each other.cognisis the only crate that depends on the four siblings together.cognis-macrosis proc-macro-only; consumed by everything that wants the derives.
cognis-core).
Where new code goes
| Concept | Crate |
|---|---|
| LLM client, provider, chat options, tool dispatch, structured output | cognis-llm |
| Embeddings, vector stores, retrievers, splitters, loaders, indexing | cognis-rag |
Graph<S>, nodes, channels, reducers, checkpointers, viz | cognisgraph |
| Tracing / observability adapter (Langfuse, OTel, …) | cognis-trace |
| Agent loop, multi-agent, agent bus, middleware, built-in tools, memory | cognis |
| Pure traits / types everyone needs (Runnable, prompts, output parsers, error, Message) | cognis-core |
| Anything that does I/O against an external service | feature-gated, opt-in |
cognis. Agent policy building blocks (retry, rate limiting, PII, redaction, model fallback) live in cognis too — they share the same Middleware trait.
Design patterns (mandatory)
These shape every feature in the codebase. Follow them when adding new code.Traits, not classes
Each capability is a trait with a small required surface and generous provided defaults. NewMemory impls implement read/write/clear and inherit seed. New RateLimiter impls implement acquire(estimated_tokens) and inherit the policy combinators.
When adding a new variant of an existing trait, mirror the builder methods and naming of its siblings. A new Memory variant ships with_system(...) because the others do.
Builders return Self
with_X(self, x) -> Self. Constructors don’t take optional args — promote them to builder methods.
Enums for closed sets
Where Python uses union types or magic strings, Rust uses enums with exhaustive matching. Examples:Message, ContentPart, ToolChoice, StreamMode, Goto, Durability.
Generic Runnable, not Value-typed
Runnable<I, O> is generic — never Value-typed at trait boundaries. Use serde_json::Value only at system edges (user input, persistence, wire serialization). Heterogeneous composition uses type-erased wrappers (DynRunnable).
Errors are actionable
Each crate below the umbrella defines its own error type viathiserror. Cross-crate errors use From conversions — cognis_graph::Error wraps cognis_core::CognisError.
The umbrella cognis crate does not depend on thiserror directly. When adding a new error type there, hand-roll Display and Error.
Async by default
All I/O-bound trait methods areasync via #[async_trait]. No sync compat layer; callers use block_on if they need to.
Feature flags for optional deps
Every external integration is behind a feature flag. The core crates compile with no network deps. New providers, vector stores, and exporters all gain a feature.Code quality rules
- All public types, traits, and functions get
///doc comments. - No
unwrap()orexpect()in library code — propagate errors with?. - No
println!in library code — usetracingmacros. - Clippy passes:
cargo clippy --workspace --features all-providers -- -D warnings. - Format with
cargo fmtbefore every commit. - New public API gets at least one unit test and one doc-test.
What NOT to port from Python
| Python pattern | Rust approach |
|---|---|
Chain base class (deprecated upstream) | Compose with Runnable and pipe instead. |
| Pydantic runtime validation | serde for deserialization + custom validators at boundaries. |
@classmethod constructors | Associated functions or builder pattern. |
| Mixin classes | Trait composition, no mixins. |
**kwargs pass-through | Explicit config structs or builder methods. |
| Global callback manager | Thread-local or config-carried CallbackManager. |
asyncio.to_thread() for sync compat | Async-only API; callers use block_on() if needed. |
Dynamic attribute access (getattr) | Enum dispatch or trait objects. |
See also
Adding a provider
The walkthrough for a new LLM client.
PR guidelines
The PR checklist that maps to these rules.
Reference → cognis
The umbrella’s re-export surface.