19 breaking releases
Uses new Rust 2024
| new 0.28.0 | Jul 15, 2026 |
|---|---|
| 0.26.0 | Jul 8, 2026 |
#2578 in Artificial intelligence
Used in 2 crates
32KB
782 lines
Nenjo
Beta — Nenjo is under active development. APIs may change between releases.
An open-source Rust SDK and platform worker for building portable, provider-agnostic agentic AI workflows.
Nenjo gives you a programmable agent engine with tool use, persistent memory, multi-agent delegation, routine orchestration, and platform worker integration, while keeping the core SDK decoupled from any single LLM provider or transport.
Install
curl -fsSL https://nenjo.ai/install | bash
The installer places the nenjo, nenpm, and nenjoup binaries in
~/.nenjo/bin by default. nenjo update and nenpm update update the
installed binary bundle through the bundled nenjoup updater. Set
NENJO_NO_UPDATE_CHECK=1 to suppress passive update-available notices.
Docker
The worker image is published to GitHub Container Registry:
docker run --rm \
-e NENJO_API_KEY="$NENJO_API_KEY" \
-e OPENAI_API_KEY="$OPENAI_API_KEY" \
-v nenjo-data:/home/nenjo/.nenjo \
ghcr.io/nenjo-ai/nenjo-worker:latest
The image runs nenjo run by default. Persist /home/nenjo/.nenjo to keep
worker config, manifests, package installs, memory, crypto state, and session
state across container restarts. Mount a host checkout when the worker should
operate on a specific workspace:
docker run --rm \
-e NENJO_API_KEY="$NENJO_API_KEY" \
-e OPENAI_API_KEY="$OPENAI_API_KEY" \
-e NENJO_CAPABILITIES=chat,task,repo \
-v nenjo-data:/home/nenjo/.nenjo \
-v "$PWD:/home/nenjo/.nenjo/workspace" \
ghcr.io/nenjo-ai/nenjo-worker:latest
Use versioned tags for pinned deployments:
docker pull ghcr.io/nenjo-ai/nenjo-worker:v0.12.0
Container updates should use docker pull and container replacement, not
nenjo update. The images set NENJO_NO_UPDATE_CHECK=1 so container logs do
not suggest self-updating an immutable image.
Two image variants are published:
| Image | Use |
|---|---|
ghcr.io/nenjo-ai/nenjo-worker:<version> / latest |
Production worker baseline with git, git-lfs, shell utilities, rg, curl, wget, jq, Python, and TLS certificates |
ghcr.io/nenjo-ai/nenjo-worker:<version>-dev / dev |
Larger toolbox image with compilers, Rust, Node/npm, GitHub CLI, Docker CLI, editors, and debugging utilities |
Open an interactive shell in the dev image with:
docker run --rm -it \
-v nenjo-data:/home/nenjo/.nenjo \
-v "$PWD:/home/nenjo/.nenjo/workspace" \
--entrypoint bash \
ghcr.io/nenjo-ai/nenjo-worker:dev
Docker-backed sandboxing from inside the worker is an advanced setup. Mounting the host Docker socket gives the container Docker access equivalent to the host user:
-v /var/run/docker.sock:/var/run/docker.sock
Crates
| Crate | Description |
|---|---|
nenjo |
Core SDK: provider builder, agent turn loop, memory, manifests, abilities, domains, councils, and routines |
nenjo-tool-api |
Shared tool traits, specs, categories, calls, results, and SDK-level tool security inputs |
nenjo-knowledge |
Knowledge pack primitives, reusable knowledge tools, and optional embedded Nenjo documentation |
nenjo-models |
LLM provider trait and implementations for OpenAI, Anthropic, Gemini, OpenRouter, Ollama, and OpenAI-compatible APIs |
nenjo-xml |
XML serialization and MiniJinja template rendering for structured prompt context |
nenjo-events |
Typed command, response, stream, resource, and capability contracts for worker-to-platform messaging |
nenjo-eventbus |
Transport-agnostic event bus with NATS JetStream support |
nenjo-secure-envelope |
Secure envelope layer over the event bus, including encrypted payload helpers and codec traits |
nenjo-crypto-auth |
Worker enrollment, wrapped key state, and secure-envelope key provider primitives |
nenjo-platform |
Platform-backed manifest contracts, REST client, MCP tool contract, local backend, and access-policy helpers |
nenjo-sessions |
Shared session contracts for runtime, worker, and future session services |
nenjo-harness |
Platform command handlers, active execution/session registries, event bridging, and trace/session runtime hooks around a provider |
nenjo-worker |
Platform worker implementation behind nenjo run |
nenjo-nenpm |
Package manager install planning and lockfile/materialization logic |
nenjo-updater |
Shared update checks and binary bundle installation logic |
nenjo-cli |
CLI package that builds the nenjo binary |
nenpm-cli |
CLI package that builds the nenpm package-manager binary |
nenjoup-cli |
CLI package that builds the nenjoup updater binary |
nenjo-integration-tests |
Integration test crate for provider-backed SDK flows |
Separation Boundaries
Nenjo is split so the SDK can be embedded without pulling in the platform worker:
| Layer | Crates | Owns |
|---|---|---|
| Core SDK | nenjo, nenjo-tool-api, nenjo-models, nenjo-xml, nenjo-knowledge |
Agent execution, prompts, tool contracts, models, memory, manifests, knowledge packs |
| Platform contracts | nenjo-events, nenjo-sessions |
Transport-neutral wire and session types |
| Platform transport | nenjo-eventbus, nenjo-secure-envelope, nenjo-crypto-auth |
Event delivery, secure envelopes, worker enrollment and keys |
| Manifest bridge | nenjo-platform |
Platform REST/MCP manifest operations and local/platform synchronization |
| Harness | nenjo-harness |
Platform command handlers, provider swapping, active execution registries, session writes, traces, and event bridging |
| Worker and CLI | nenjo-worker, nenjo-cli, nenpm-cli, nenjoup-cli, nenjo-updater |
Process lifecycle, config/bootstrap, event loop, provider/tool factories, concrete runtime tools, local stores, package-manager CLI, binary updates |
CLI Worker
The nenjo binary is built by the nenjo-cli package. Its run command starts the nenjo-worker runtime, connects to the platform event bus, and processes chat messages, tasks, cron schedules, repository events, crypto enrollment, and manifest updates.
# Start the worker (uses NENJO_API_KEY from env or ~/.nenjo/config.toml)
nenjo run
# With verbose logging
nenjo run --log-level "info,nenjo=debug"
# Update the installed Nenjo command-line tools
nenjo update
The worker is resilient to service outages. Startup and the event loop use exponential backoff so the process can recover when platform services or NATS become available again.
Worker Capabilities
Workers can be scoped to handle only specific workloads:
| Capability | Handles |
|---|---|
chat |
Chat messages, domain sessions, session management |
task |
Task execution, pause, resume, cancel |
cron |
Cron schedule enable, disable, trigger |
manifest |
Resource change notifications for agents, models, routines, projects, and related manifests |
repo |
Repository sync and unsync |
Run multiple workers with different capabilities to distribute load across machines or isolate workloads.
Platform Integration
Platform-connected workers compose several crates:
nenjo-eventsdefines typed commands, responses, stream events, capabilities, and encrypted payload metadata.nenjo-eventbustransports those events over NATS JetStream or another transport implementation.nenjo-secure-envelopewraps event transport with encryption-aware encode/decode behavior.nenjo-crypto-authmanages worker enrollment and content-key access for encrypted payloads.nenjo-platformfetches bootstrap manifests, persists manifest mutations, exposes manifest MCP tools, and classifies sensitive payload content.nenjo-sessionsdefines shared session storage and coordination traits used by runtime implementations.nenjo-harnesshandles platform commands around an assembled provider and records session/trace state through runtime traits.nenjo-workerowns concrete config, bootstrap, event loop, native tools, local project knowledge sync, and file-backed session/artifact storage.
Key Features
- Provider-agnostic — swap LLM providers without changing application code
- Turn loop engine — automatic tool call execution, parallel tool dispatch, context compaction, and streaming
- Multi-agent delegation — agents delegate subtasks to other agents with cycle detection and depth limiting
- Persistent memory and artifacts — project, core, and shared memory scopes plus project/workspace artifact indexes with automatic prompt injection
- Routine orchestration — DAG-based multi-step execution with gates, councils, terminals, and cron scheduling
- Platform worker runtime — capability-scoped event handling, secure envelopes, manifest sync, and session coordination
- Knowledge packs — built-in, project, and custom documentation packs with metadata-first search and graph traversal tools
- Transport-agnostic messaging — pluggable event bus with a production-ready NATS JetStream implementation
Embedding The SDK
Use the core SDK directly when you want to run agents in your own application without the platform worker:
use nenjo::Provider;
// Build a provider with your manifest, model factory, and tools.
let provider = Provider::builder()
.with_loader(my_manifest_loader)
.with_model_factory(my_model_factory)
.with_tool_factory(my_tool_factory)
.build()
.await?;
// Look up an agent by name and run it.
let runner = provider
.agent_by_name("coder")
.await?
.build()
.await?;
let output = runner.chat("Refactor the auth module").await?;
println!("{}", output.text);
let mut handle = runner.chat_stream("Refactor the auth module").await?;
while let Some(event) = handle.recv().await {
match event {
nenjo::TurnEvent::ToolCallStart { calls } => {
for call in calls {
println!("calling {}...", call.tool_name);
}
}
nenjo::TurnEvent::Done { .. } => break,
_ => {}
}
}
let output = handle.output().await?;
You can also start from an empty provider and describe the agent at runtime. This is useful for tests, embedded flows, or callers that keep their own agent catalog:
use nenjo::manifest::AgentManifest;
use nenjo::Provider;
let agent_manifest = AgentManifest::builder()
.with_name("reviewer")
.with_system_prompt("Act as a focused review worker.")
.with_developer_prompt("Be concise and evidence-driven.")
.with_task_template("Task: {{ task.title }}\n\n{{ task.description }}")
.build()?;
let runner = Provider::builder()
.with_model_factory(model_factory)
.build()
.await?
.new_agent()
.with_agent_manifest(agent_manifest)
.with_model_manifest(model_manifest)
.build()
.await?;
Architecture
Provider::builder()
.with_loader(loader) // ManifestLoader — fetches agents, models, routines
.with_model_factory(factory) // ModelProviderFactory — creates LLM providers
.with_tool_factory(tools) // ToolFactory — creates tools per agent
.with_knowledge_packs([KnowledgePackEntry::new("docs:app", docs_pack)])
.with_memory(memory) // Memory + artifacts — persistent agent state
.build().await?
-> Provider
provider.agent_by_name("coder").await? -> AgentBuilder -> .build().await? -> AgentRunner
provider.new_agent() -> AgentBuilder -> .build().await? -> AgentRunner
runner.chat("task").await? -> TurnOutput { text, messages, tokens, tool_calls }
runner.chat_stream("task").await -> ExecutionHandle { recv(), output() }
nenjo run -> nenjo-cli -> nenjo-worker
-> secure envelope event bus
-> nenjo-harness handlers
-> Provider / AgentRunner
License
Licensed under the Apache License, Version 2.0.
Dependencies
~1.6–2.8MB
~51K SLoC