Why Nanitics is shaped this way
Lede
Nanitics is a Python SDK for engineers who build agentic systems and care about how those systems behave in production. This page exists for the reader who wants to understand the design thesis before adopting. It is for software engineers and tech leads who already know they will build with one SDK or another and are trying to decide which one matches the way they write code. The rest of the site shows what the SDK does. This page covers why it has the shape it has.
Composable primitives, not a framework
Nanitics is shaped as a library of small, independent primitives. An agent strategy is a class. A coordination pattern is a class. A memory store is a class. A planner is a class. None of them know about each other beyond the narrow protocols they share. An author composes them by passing instances into constructors. Nothing imposes a shape on the program around them.
The trade-off is real. A framework would deliver a faster path to a working demo. It would supply opinionated defaults for orchestration, persistence, and deployment. It would give a reader a single answer to “how do I build this.” Nanitics declines that answer. The cost is a steeper learning curve for the first few weeks. The benefit is that the SDK does not lock the application into a runtime, a database choice, a web framework, or a workflow shape that the application would otherwise be forced to live with for years.
Composable primitives also mean breaking changes are localised. When a primitive needs to evolve, the change touches the primitive’s public surface, not a top-down framework lifecycle. The deprecation policy and the changelog record the contract for change so an adopter can plan around it rather than discover it after upgrade.
A composable library asks more of an author than a framework asks. The author chooses the orchestration shape. The author chooses the persistence layer. The author decides whether the application is a CLI, a job runner, an HTTP server, or a long-running daemon. Nanitics treats those decisions as the author’s to make. The library supplies the primitives the author composes inside whichever shell they pick.
Trace-first observability as a design discipline
Every primitive in Nanitics emits structured events. An agent loop emits events for each iteration. A tool call emits events for invocation, return, and error. A coordination handoff emits events for the source agent, the target agent, and the message that crossed between them. An evaluator emits events for verdict and rationale. The events are not optional and not configured on; they are what the primitives emit by default.
The Observatory trace viewer renders these events as a hierarchical timeline. The viewer is not a separate service to bolt on. It runs against the events the SDK already produces. An author who instruments nothing still has a usable trace.
This shapes how an engineer writes code with the SDK. Adding a new behaviour means asking what events the behaviour should emit, before asking what data structure should hold its state. Observability is not a late-stage concern. It is the discipline that determines whether the primitive is well-formed.
The trace also changes how teams debug agentic systems. A failed run renders as a hierarchical tree: which agent decided what, which tool returned which payload, which evaluator rejected which attempt, where the loop broke. Teams use the same event stream to debug failures and to audit behaviour after the fact.
Real-services validation
Mocked tests answer one question: did the code do what the test expected. Real-service tests answer a different question: does the public surface behave the way the documentation claims when bound to a real LLM, a real embedding service, and a real search provider. Both questions matter. The Nanitics test suite answers the first at one hundred per cent line coverage. The validation suite answers the second by running every public component against real providers under a separate gate.
MockLLMClient and MockEmbeddingClient mirror the real client behaviour
closely enough that an example built against the mocks runs unchanged
against the real providers when the user swaps the client. The shape of
the mock is the shape of the contract. The validation suite enforces that
the contract holds.
The cost is a longer development loop for any change that touches the public surface. The benefit is that the public surface is mature in a way that pure mock-based testing cannot certify. Pre-1.0 status is named honestly because the validation suite reveals which corners of the surface are stable and which are still settling.
The maturity model
Nanitics is pre-1.0. The maturity model is “matures through use” rather than “ships a complete API surface, then declares stability.” Every release records the parts of the public surface that have been exercised in real applications, the parts that have been validated against real providers, and the parts that have not yet been pressure-tested.
Breaking changes happen. They are documented in the changelog and follow the deprecation policy. A reader who plans to depend on a primitive can read the changelog history for that primitive and form a view about how likely the contract is to change.
What the version number signals matters more than the number itself. A 1.0 SDK that hides instability behind a stable-sounding label is worse than a pre-1.0 SDK that names what is settling and what is not. Pre-1.0 is the honest label for the surface as it stands.
Documentation philosophy
One source of truth per concept. Docstrings carry API details. Guides carry decision guidance. Examples carry runnable patterns. No layer duplicates another.
Docstrings are anchored to the file they describe. A reader who jumps to the source via the editor sees the documentation alongside the implementation. Drift is harder because the two live in the same file.
Guides under docs/guides/ cover decision guidance: when to reach for
the primitive, what trade-offs the choice involves, what the primitive
costs and what it buys. Guides do not repeat the API signature. They
reference the docstring for that.
Examples under examples/ cover runnable usage. Every example is a
complete program with no missing imports and no half-defined helpers. An
adopter can copy the example into a fresh file, install the SDK, and run
it without further setup.
What this means for adopters
Read the Getting Started guide first. It is the shortest path from “I have heard of Nanitics” to “I have a working program in front of me.” It calls out where the docstrings, guides, and examples cover deeper detail so a reader who wants more knows where to look.
File issues that move the SDK forward. A focused issue with a minimal reproduction, the SDK version, and the observed and expected behaviour is the most efficient unit of work for the maintainers. Discussions are the right place for design questions and feature requests; the issue tracker is the right place for bugs and behavioural surprises.
Plan for breaking changes. Pre-1.0 status is named so the maturity contract is explicit. The deprecation policy describes the notice an adopter receives before a primitive evolves. An adopter who tracks the changelog and pins the SDK version in their lockfile has a quiet upgrade path.
Ask questions where the maintainers will see them. GitHub Discussions is the canonical channel for design questions, integration questions, and clarifications about the documentation. The maintainers read it and respond there.