Soothe Nano — batteries-included SootheNanoAgent on deepagents
Project description
soothe-nano
A ready-to-run coding agent you can drop into a script, CLI, or app.
Built on soothe-deepagents (filesystem, shell, subagents, skills, MCP). Nano adds the pieces you usually wire yourself: workspace safety, progressive tools/skills, research subagents, and a config-driven factory.
Vision
Give builders a production-shaped SootheNanoAgent in a few lines of Python.
- Start small — chat, tools, or full composition
- Stay portable — embed in notebooks, CLIs, or your own service
- Compose what you need — tools, memory, subagents, skills, and MCP via config
Architecture
soothe-deepagents agent harness (FS, shell, memory, skills base)
↓
soothe-sdk shared contracts (protocols, events)
↓
soothe-nano SootheNanoAgent + toolkits + subagents + MCP
create_nano_agent(config)
│
├─ model + middleware stack
├─ tools (builtin groups + yours)
├─ subagents (planner, research, browser, …)
├─ skills (progressive discovery)
└─ MCP (on-demand activation)
Features
| Area | What nano provides |
|---|---|
| Tools | Builtin groups: shell, file ops, HTTP, search, data, … |
| Subagents | Ready: plan, deep/academic research, browser |
| Skills / tools in context | Progressive loading — activate what the turn needs |
| Workspace | Scoped workspace + security defaults |
| Config | YAML / SootheConfig factory |
| Memory | Optional long-term memory via protocols |
| MCP | Registry and on-demand adapters |
vs deepagents
| deepagents | soothe-nano | |
|---|---|---|
| What you get | Opinionated harness | Harness plus coding product defaults |
| Tools | Bring your own | Builtin groups out of the box |
| Subagents | You define them | Ready plan / research / browser |
| Skills / tools in context | Base support | Progressive loading |
| Workspace | Pluggable backends | Scoped workspace + security defaults |
| Config | Code-first | YAML / SootheConfig factory |
Use deepagents when you want a minimal harness and full control.
Use nano when you want a coding agent that already knows how to work in a repo.
When to use nano
| Scenario | Fit |
|---|---|
| Coding assistant in a repo | ✅ Files, shell, plan out of the box |
| Research / browsing agent | ✅ Deep research, academic, browser subagents |
| Embed in your product | ✅ Library API, no daemon required |
| One-shot / headless CLI | ✅ See fj-ai |
| Plugin / toolkit author | ✅ Depends on nano only |
| Simple Q&A chat | ✅ Strip tools/subagents as needed |
Install
uv add soothe-nano
Quick start
from soothe_nano import create_nano_agent
from soothe_nano.config import SootheConfig
agent = create_nano_agent(SootheConfig())
# agent.ainvoke / streaming — see examples/
Library examples live in examples/:
- Pure model (no tools)
- With tools
- With memory
- With subagents
- Full composition
python packages/soothe-nano/examples/01_pure_nano_example.py
Productive CLI (reference: fj-ai)
fj-ai is a production one-shot coding CLI built only on soothe-nano (no soothe daemon). Use it as the integration blueprint:
pip install fj-ai # or: uv tool install fj-ai
fj explain this repo
fj -f what did we decide last time?
Integration pattern
A headless CLI typically does four things on top of nano:
- Load config —
~/.soothe/config/nano.yml, or zero-config fromOPENAI_API_KEY/ANTHROPIC_API_KEY - Force SQLite for standalone runs (threads survive across process exits)
- Build the agent with
create_nano_agent, pin workspace, attach a checkpointer - Stream
agent.astream(...)and close theaiosqliteconnection on exit
Minimal sketch (same shape as fj_ai/agent.py):
from __future__ import annotations
import asyncio
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Any, AsyncIterator
from soothe_nano import SootheNanoAgent, create_nano_agent
from soothe_nano.config import SOOTHE_HOME, SootheConfig
from soothe_nano.resolve import resolve_checkpointer
def load_config(path: Path | None = None) -> SootheConfig:
cfg = path or (SOOTHE_HOME / "config" / "nano.yml")
if cfg.is_file():
return SootheConfig.from_yaml_file(str(cfg))
return SootheConfig() # OPENAI_API_KEY / ANTHROPIC_API_KEY
def apply_cli_defaults(config: SootheConfig) -> SootheConfig:
durability = config.agent.protocols.durability.model_copy(
update={"backend": "sqlite", "checkpointer": "sqlite"}
)
protocols = config.agent.protocols.model_copy(update={"durability": durability})
agent = config.agent.model_copy(update={"protocols": protocols})
persistence = config.persistence.model_copy(update={"default_backend": "sqlite"})
return config.model_copy(update={"agent": agent, "persistence": persistence})
@asynccontextmanager
async def open_sqlite_checkpointer(config: SootheConfig) -> AsyncIterator[Any | None]:
result = resolve_checkpointer(apply_cli_defaults(config))
db_path = result[1] if isinstance(result, tuple) and isinstance(result[1], str) else None
if not db_path:
yield None
return
import aiosqlite
from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
from soothe_sdk.utils.serde import create_soothe_serde
Path(db_path).parent.mkdir(parents=True, exist_ok=True)
conn = await aiosqlite.connect(db_path)
checkpointer = AsyncSqliteSaver(conn, serde=create_soothe_serde())
await checkpointer.setup()
try:
yield checkpointer
finally:
await conn.close() # required — aiosqlite uses a non-daemon thread
async def build_agent(
config: SootheConfig,
*,
checkpointer: Any | None = None,
) -> SootheNanoAgent:
agent = create_nano_agent(apply_cli_defaults(config))
if checkpointer is not None:
agent.graph.checkpointer = checkpointer
return agent
async def run_once(query: str, *, thread_id: str) -> None:
config = load_config()
async with open_sqlite_checkpointer(config) as checkpointer:
agent = await build_agent(config, checkpointer=checkpointer)
async for chunk in agent.astream(
query,
config={"configurable": {"thread_id": thread_id}},
stream_mode=["messages", "updates", "custom"],
):
# render tokens / tool progress to stdout (see fj_ai/stream.py)
_ = chunk
if __name__ == "__main__":
asyncio.run(run_once("summarize this repo", thread_id="cli-demo"))
What fj adds on top of nano
| Concern | fj-ai approach |
|---|---|
| UX | One-shot fj <query…>; -f / -t resume threads; -l list |
| Persistence | SQLite checkpointer under $SOOTHE_DATA_DIR |
| Skills | Package builtin_skills/ via register_builtin_skill_root |
| Workspace | SOOTHE_WORKSPACE / cwd for file + shell tools |
| Streaming | Quiet progress line + full final answer (stream.py) |
| Setup | fj setup writes ~/.soothe/config/nano.yml |
For a full TUI / StrangeLoop host on the same stack, see mirasoth/soothe. For the slim CLI product, clone caesar0301/fj-ai.
Package layout
soothe_nano/
agent/ SootheNanoAgent, create_nano_agent
config/ SootheConfig
toolkits/ Builtin tool groups
subagents/ plan, research, browser, …
middleware/ Progressive tools/skills, workspace, policy
skills/ Catalog + progressive search
mcp/ MCP registry / adapters
backends/ Persistence helpers
Development
From packages/soothe-nano/:
make help # list targets
make sync-dev # sync deps
make format lint # format + lint
make test-unit # unit tests
make test-integration # integration tests (--run-integration)
make examples # run examples
make build # build dist/
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file soothe_nano-1.0.6.tar.gz.
File metadata
- Download URL: soothe_nano-1.0.6.tar.gz
- Upload date:
- Size: 470.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b62887ff05aae22b4944df5e27f9d25013aca39fa2ad5095788e7f89703a6a7d
|
|
| MD5 |
364e2501704beee837787a6fd6642645
|
|
| BLAKE2b-256 |
7f93d0202186799f43835cf695646f890d177f72b86ed2f35dde2244c509912a
|
File details
Details for the file soothe_nano-1.0.6-py3-none-any.whl.
File metadata
- Download URL: soothe_nano-1.0.6-py3-none-any.whl
- Upload date:
- Size: 624.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56ced34dce28a5d24d0c25f5495d7a6d76f3e2f4f5b7d89230a206a99cb6c81e
|
|
| MD5 |
a4a1313a1509f084a2028fda6a48c4ee
|
|
| BLAKE2b-256 |
a6b8d00f2c3db62542c4eac76a04e9a6a220eda6129b82a774ab8805dc9bd06b
|