nuvel — building production-ready ADK agents from inside Claude Code
nuvel is a meta-agent CLI that scaffolds a battle-tested Google ADK skeleton and ships a library of ADK knowledge skills (agent patterns, prompt engineering, callbacks/HITL, streaming, tool creation, skill design). When the user wants an agent, your job is to drive nuvel to produce the skeleton, then fill in the brain — tools, prompts, domain skills — using the bundled knowledge.
Repo: https://github.com/Folken2/nuvel.
Make sure nuvel is callable
Before invoking the CLI, confirm it's available:
nuvel --help # if this prints usage, you're good
If command not found:
- The user is probably inside the nuvel repo with the venv unactivated. Try
.venv/bin/nuvel --helpfirst — that's the most common case. - If there's no venv yet, run
pip install -e .from the repo root (orpython3 -m venv .venv && .venv/bin/pip install -e .to create one). After this,.venv/bin/nuvelworks; or activate the venv (source .venv/bin/activate) and use plainnuvel. - If the user hasn't cloned the repo, ask before cloning — nuvel only ships from source today (
git clone https://github.com/Folken2/nuvel.git).
Throughout the rest of this skill nuvel means "whichever invocation works on this machine" — substitute .venv/bin/nuvel if the venv isn't activated.
Two modes — pick the right one
Mode A — Scaffold-and-edit (default for Claude Code). You drive everything: run nuvel agent create for the skeleton, then write the tools / prompts / skills yourself, consulting nuvel skills for ADK conventions. This is almost always the right choice in Claude Code because you are the smart part — you can read files, reason, and iterate, which beats a one-shot LLM scaffold.
Mode B — Meta-agent autopilot. Run nuvel run --dev to launch the meta-agent server (FastAPI on :8000), then talk to it via the ADK web UI or /run_sse/. Use this only if the user explicitly asks for the autonomous flow, or wants a demo. Requires OPENROUTER_API_KEY in the repo's .env.
When in doubt: Mode A.
Feature flags — --persona, --with-composio, --workflow, --with-acp
nuvel agent create ships several optional bundles. Pick them up front; they shape the scaffold meaningfully and aren't easy to retrofit.
--persona — activates the self-evolving agent pattern: a self-rewriting SOUL.md (with read_soul / update_soul tools), a one-time AWAKENING.md bootstrap that the agent deletes via complete_awakening, and skill-authoring tools (author_skill, update_skill) so the agent grows its own SKILL.md repertoire over time. The instruction frame switches to the "act-first" persona text. Use this for agents meant to live for months and develop a stable character — personal assistants, long-running companions, agents that should accumulate knowledge across sessions. Do not use for stateless task bots, customer-support agents, or anything that should behave consistently across deploys: a support bot that rewrites its own SOUL.md mid-conversation is a regression, not a feature.
--with-composio — wires the Composio Tool Router via ADK's McpToolset. One composio.create(user_id=...) call gives the agent ~1000 toolkits (Gmail, GitHub, Slack, Notion, Calendar, etc.) behind a single hosted MCP endpoint. Composio handles auth, tool discovery, and execution. Requires COMPOSIO_API_KEY at runtime; without it the toolset gracefully no-ops. Use this when the agent's value is breadth of integrations rather than depth in one domain. Independent of --persona — combine freely.
--workflow — makes the root agent an ADK 2.0 Workflow graph (agent_workflow.py) instead of a single LlmAgent: a planning node and an execution node, both mode='task' with output_schema contracts, plus a deterministic routing node between them. agent.py becomes a shim re-exporting root_agent, so every import path is unchanged. Use it when the agent's work is genuinely multi-step with branching — plan-then-execute, triage-then-route, draft-then-review. Skip it for a single-purpose tool-using agent; a graph you don't need is just indirection. Read adk-task-delegation and adk-workflow-graphs before editing the graph.
--with-acp — makes the agent ACP-compatible and CLI-runnable. Adds an acp/ package implementing the Agent Client Protocol (JSON-RPC 2.0 over stdio — the protocol Zed and other editors use to drive an agent as a subprocess) and a cli.py local terminal entrypoint. Run the protocol adapter with python -m <pkg>.acp (an editor spawns this and speaks initialize → session/new → session/prompt over the pipe); run the plain CLI with python -m <pkg>.cli "prompt" (one-shot) or python -m <pkg>.cli (REPL). Both reuse the same AgentHarness-wired Runner as the FastAPI server, so tools/plugins/memory/cost tracking behave identically. The ACP adapter also honors the editor's session capabilities: mcpServers declared in session/new (stdio / HTTP / SSE) are wired into that session's agent as tools, when the client advertises fs capabilities the agent gets read_text_file / write_text_file tools that operate on the editor's filesystem view (unsaved buffers included), and sensitive tool calls are gated by an editor approval prompt via session/request_permission (HITL — tune with ACP_PERMISSION_MODE = off/sensitive/all and ACP_PERMISSION_TOOLS). Independent of the other flags — combine freely. Use it when the agent should be usable from an editor or a shell, not only as an HTTP server. ADK-only (the other backends reject the flag).
When to combine. Personal agent meant to act across the user's whole digital life: --persona --with-composio. Pure task bot needing many integrations: --with-composio only. Domain-specialist that should never drift (e.g. SQL analyst, data-pipeline operator): no flags. Personal companion without external tools: --persona only.
Universal improvements (always on, regardless of flags):
LazySkillToolsetrebuilds onSKILL.mdmtime change — new skills become queryable on the next agent invocation, no process restart. SOUL.md and memory edits are also picked up immediately (read fresh each turn).config/paths.pyexposesSOUL_FILE/AWAKENING_FILE/SKILLS_DIR/MEMORY_DIRenv vars with in-repo defaults. Set these to a mounted volume path (e.g./data/...on Railway) for cross-deploy persistence; leave unset locally.seed_volume_if_empty()runs at boot and copies in-repo seeds into an empty volume on first deploy.
The canonical Mode A workflow
Treat each step as a checkpoint — verify the previous step before moving on. Don't batch 5 steps and hope.
1. Confirm the spec with the user (always)
Before scaffolding, get clarity on three things — silently if obvious from context, explicitly if not:
- Name (kebab-case, ≤40 chars, must start with a letter, no consecutive hyphens —
nuvel agent createvalidates this). - One-line description — used in the README and as a hint for prompt design.
- What the agent actually does — list the tools and the trigger phrases. This is what you'll spend most of your time on; the skeleton is free.
If the user gave you a vague brief ("an agent that helps with X"), name 2-3 concrete tools you'd build and ask if that's the shape. Don't scaffold based on guesswork — nuvel new is fast but rewriting domain logic later is not.
2. Scaffold the skeleton
nuvel new <kebab-name> \
--description "one-line description" \
--output-dir ./generated-agents \
[--persona] [--with-composio] [--workflow] [--with-acp]
The default --output-dir is ./generated-agents relative to wherever you run from. See the Feature flags section above to decide on --persona, --with-composio, --workflow, and --with-acp. Pass --system-prompt only if the user gave you exact text — otherwise leave it off and write the prompt properly in step 4.
Verify: ls generated-agents/<name>/ should show <snake_name>/, run_adk.py, requirements.txt, .env.example, tests/.
3. Survey the relevant ADK knowledge
nuvel bundles 15 ADK knowledge skills. Don't read them all — pick by topic:
nuvel skills list # see what's available
nuvel skills search <topic> # narrow by keyword
Available skills (all live in nuvel/backends/adk/skills/<slug>/SKILL.md inside the nuvel repo):
| Slug | Read when… |
|---|---|
adk-agent-patterns |
Choosing the top-level shape — single LlmAgent vs. Workflow graph vs. multi-agent |
adk-workflow-graphs |
Building a Workflow — nodes, edges, routing, fan-out/fan-in, dynamic nodes |
adk-task-delegation |
Sub-agent delegation — mode='task'/'single_turn'/'chat', finish_task, typed contracts |
adk-tool-creation |
Writing function tools (signatures, ToolContext, errors) |
adk-prompt-engineering |
Designing the system prompt — dynamic instructions, InstructionProvider |
adk-callbacks-hitl |
Adding human-in-the-loop gates, before/after callbacks, state |
adk-streaming |
Voice / video / Gemini Live API agents |
adk-skill-creation |
Authoring SKILL.md files for the agent's own domain knowledge |
adk-skill-design-patterns |
Five canonical skill shapes — pick before writing one |
adk-composio-tool-router |
Wiring the Composio Tool Router MCP (--with-composio) |
adk-long-horizon-guardrails |
Halt guards, argv-level shell command safety, exfil guard for agents that run unattended or long |
adk-long-horizon-sessions |
Resumability and event compaction for sessions that span many turns or restarts |
adk-cron-isolation |
Scoped secrets, headless tool policy, HITL-gated job creation for scheduled/cron agent runs |
adk-org-memory-retrieval |
Org-scoped memory wiring, hybrid RRF retrieval, knowledge graph queries |
adk-memory-self-improvement |
Experimental — consolidation, judge forks, skill curator for self-improving memory |
Read the SKILL.md directly with the Read tool — they're tuned for progressive disclosure (short top, deep references).
Agents meant to run unattended or long should read adk-long-horizon-guardrails and adk-long-horizon-sessions before deploy — both describe default-on behaviour (halt guards, resumability, compaction) that changes how the agent behaves under load.
4. Fill in the brain
The scaffold gives you the skeleton; now write the actual agent. In generated-agents/<name>/<snake_name>/:
tools/— write one Python file per tool, followingadk-tool-creation. UseToolContextcorrectly, return structured dicts, raise specific exceptions.prompt/instructions.py— system prompt. Applyadk-prompt-engineering; preferInstructionProviderfor any state-dependent text.skills/— domain SKILL.md files for knowledge the agent needs at runtime (escalation rules, API quirks, lookup tables). Applyadk-skill-design-patternsto pick a shape.agent.py— wire the tools and SkillToolset together. The scaffold already has the skeleton; you mostly add tool imports and register them.tests/— mirror existing test files. Add a unit test per tool and an end-to-end smoke test.
5. Verify
cd generated-agents/<name>
python -m pytest tests/ -q # tests must pass
python -c "from <snake_name>.agent import root_agent; print(root_agent.name)" # imports cleanly
If the user wants to actually run it: cp .env.example .env, add their OPENROUTER_API_KEY, then python run_adk.py. The agent runs at http://localhost:8000.
Suppressing CLI startup noise
nuvel prints two lines of dependency warnings (authlib deprecation, SKILL_TOOLSET experimental flag) to stderr on every invocation. They're harmless. If the noise gets in the way of parsing output, redirect stderr:
nuvel skills list 2>/dev/null
Don't try to fix the warnings — they're upstream and the project tolerates them deliberately.
Common pitfalls
- Kebab vs snake confusion. The agent name is kebab-case (
my-agent), but the Python package inside is snake_case (my_agent). The scaffolder handles the conversion; just don't passmy_agenttonuvel new. - Running
nuvel runfor scaffolding.nuvel runlaunches the meta-agent server; it doesn't create files. Usenuvel newto create. - Skipping the knowledge skills. The bundled skills exist because getting ADK right is non-obvious. Reading
adk-tool-creationbefore writing tools saves more time than it costs every single time. - Generating a "smart" scaffold via
nuvel new --system-prompt "...". The flag literally drops your text into the template; it doesn't refine or validate. Write the prompt properly inprompt/instructions.pyafter scaffolding instead. - Working outside the nuvel repo.
nuvel newis happy to scaffold anywhere via--output-dir, but the bundled skills (nuvel skills list) only resolve when you have nuvel installed. If the user wants the agent in a different repo, scaffold inside nuvel first, thenmv generated-agents/<name>to its final home.
Quick reference
# Scaffold (base)
nuvel new <kebab-name> --description "…" --output-dir ./generated-agents
# Self-evolving personal agent with broad tool access
nuvel new <kebab-name> --description "…" --persona --with-composio
# Just persona (no external integrations)
nuvel new <kebab-name> --description "…" --persona
# Just Composio (stateless task bot with many integrations)
nuvel new <kebab-name> --description "…" --with-composio
# ACP-compatible + CLI-runnable (editor subprocess + terminal REPL)
nuvel new <kebab-name> --description "…" --with-acp
# then: python -m <snake_name>.acp (Agent Client Protocol over stdio)
# python -m <snake_name>.cli "…" (one-shot) | python -m <snake_name>.cli (REPL)
# Knowledge
nuvel skills list
nuvel skills search prompt
# Autopilot mode (only when asked)
nuvel run --dev
When the user says "build me an X agent", the answer is almost never "let me think about it" — it's "let me scaffold the skeleton and then we'll fill in the tools." Show progress; the skeleton is free.