Quick Start — Python
Build a fully wired agent with routing, tools, and memory — then run it locally in under five minutes.
-
Install Nerva
Terminal window pip install otomus-nervaRequires Python 3.11+.
-
Scaffold a project
Terminal window npx nerva new my-agent --lang pythoncd my-agentThis creates a project with
main.py,nerva.yaml, and a sample handler. -
Build a weather agent
Create
main.py:import asynciofrom nerva import Orchestrator, ExecContextfrom nerva.router import RuleRouter, Rulefrom nerva.runtime.inprocess import InProcessRuntimefrom nerva.tools import FunctionToolManagerfrom nerva.memory import TieredMemoryfrom nerva.memory.hot import InMemoryHotMemoryfrom nerva.responder import PassthroughResponderfrom nerva.registry import InMemoryRegistryfrom nerva.policy import NoopPolicyEngine# -- Tools -------------------------------------------------------------------tools = FunctionToolManager()@tools.tool("get_weather", "Get current weather for a city")async def get_weather(city: str) -> str:# Replace with a real API callreturn f"22°C and sunny in {city}"# -- Handler -----------------------------------------------------------------async def weather_handler(input, ctx):result = await tools.call("get_weather", {"city": "Berlin"}, ctx)return result.output# -- Runtime -----------------------------------------------------------------runtime = InProcessRuntime()runtime.register("weather_agent", weather_handler)# -- Orchestrator ------------------------------------------------------------orchestrator = Orchestrator(router=RuleRouter(rules=[Rule(pattern=r"weather", handler="weather_agent", intent="weather"),],default_handler="weather_agent",),runtime=runtime,tools=tools,memory=TieredMemory(hot=InMemoryHotMemory()),responder=PassthroughResponder(),registry=InMemoryRegistry(),policy=NoopPolicyEngine(),)# -- Run ---------------------------------------------------------------------async def main():ctx = ExecContext.create(user_id="user_1")result = await orchestrator.handle("What's the weather in Berlin?", ctx)print(result.text)asyncio.run(main()) -
Run it
Terminal window python main.py# Output: 22°C and sunny in Berlin
Trace output
Every request produces a structured trace so you can see exactly what happened:
[req_abc] handle "What's the weather in Berlin?" (52ms) +-- [req_abc.1] router.classify (1ms) | +-- intent=weather, handler=weather_agent, confidence=1.0 +-- [req_abc.2] runtime.invoke weather_agent (48ms) | +-- [req_abc.2.1] tools.call get_weather (45ms) +-- [req_abc.3] responder.format (1ms)Next steps
- Add more agents — register additional handlers and routing rules
- Use memory — pass
InMemoryHotMemoryto persist conversation across turns - Add middleware — inject logging, auth, or rate limiting into the pipeline
- Switch routers — swap
RuleRouterforEmbeddingRouterwhen you have 10+ agents - Read the Primitives Overview to learn what each piece does