Metadata-Version: 2.4
Name: nobelagentic
Version: 0.1.2
Summary: The agent framework that gets out of your way. One kernel, three APIs, any model.
License-Expression: MIT
Project-URL: Homepage, https://github.com/davolu/nobelagentic
Project-URL: Documentation, https://nobelagentic.vercel.app
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.0
Requires-Dist: httpx>=0.27
Requires-Dist: typer>=0.12
Requires-Dist: rich>=13.0
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.40; extra == "anthropic"
Provides-Extra: openai
Requires-Dist: openai>=1.50; extra == "openai"
Provides-Extra: mcp
Requires-Dist: mcp>=1.2; extra == "mcp"
Provides-Extra: all
Requires-Dist: anthropic>=0.40; extra == "all"
Requires-Dist: openai>=1.50; extra == "all"
Requires-Dist: mcp>=1.2; extra == "all"
Requires-Dist: duckduckgo-search>=6.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
Dynamic: license-file

# NobelAgentic (Python)

**Agents that get out of your way.** One kernel, three APIs, any model.

```python
from nobelagentic import Agent, tool

@tool
def get_weather(city: str) -> str:
    """Current weather for a city."""
    return f"{city}: 31°C, humid"

agent = Agent("You help plan trips", tools=[get_weather, "web", "time"])
print(agent.run("What's the weather in Lagos right now?"))
```

No model named → nobelagentic picks one from whatever API key is in your environment.
No schemas written → type hints and the docstring *are* the schema.
Errors tell you what to do, not just what broke.

## Install

```bash
pip install -e ".[all,dev]"      # everything
pip install -e ".[anthropic]"    # or just one provider
```

Set `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY` — or run Ollama locally and use `model="ollama:llama3.1"`.

## The three levels

| Level | You write | Who it's for |
|---|---|---|
| `Agent` | one line | 90% of use cases — a model, instructions, tools |
| `Crew` *(v0.3)* | agents + tasks + process | multi-agent, role-based teams |
| `Graph` *(v0.2)* | nodes + edges + state | full control, cycles, human-in-the-loop |

All three compile to the same runtime, so streaming, tracing and checkpoints behave identically everywhere.

## Tools

```python
Agent(tools=[
    my_function,          # any function — sync or async
    "web", "files",       # built-in packs
])
```

Built-in packs (`nobelagentic tools list`): `web` `files` `shell` `time` `math` `data`.
Packs are lazy-loaded; `shell` is opt-in only.

## MCP

```python
Agent(mcp=["github", "postgres"])                       # registry names
Agent(mcp=["https://my-server.example.com/mcp"])        # remote
Agent(mcp=[{"command": "npx", "args": ["-y", "some-mcp-server"]}])
```

`nobelagentic mcp add myserver "npx -y some-mcp-server"` registers one for every project.

## Handoffs

```python
spanish = Agent("You only speak Spanish", name="spanish")
triage  = Agent("Route by language", handoffs=[spanish])
triage.run("Hola!")   # → spanish answers
```

## Orchestration

A handoff transfers the conversation. An orchestrator keeps control — sub-agents become tools it can call, combine and build on:

```python
researcher = Agent("You find facts.", name="researcher", tools=["web"])
writer     = Agent("You write crisp prose.", name="writer")

boss = Agent("Produce short reports. Delegate, then combine.",
             tools=[researcher.as_tool(), writer.as_tool()])
boss.run("One paragraph on African fintech")
```

## Streaming and events

```python
async for ev in agent.stream("..."):
    match ev:
        case TextDelta(text):        print(text, end="")
        case ToolCallStart(call):    print("calling", call.name)
        case RunEnd(output, usage):  print(usage)
```

## Models

```python
Agent(model="claude-opus-5-5")          # prefix → provider
Agent(model="openai:gpt-5")             # explicit
Agent(model="groq:llama-3.3-70b")       # any OpenAI-compatible host
Agent(model=MyProvider())               # bring your own
```

## CLI

```
nobelagentic run "What is 15% of 240?"
nobelagentic chat --tools web,files --mcp github
nobelagentic tools list
nobelagentic mcp list | add
```

## Roadmap

- **v0.1** ✅ provider layer · `@tool` · ReAct loop · streaming · packs · MCP client · handoffs · CLI
- **v0.2** graph kernel (nodes, typed state, checkpoints, resume) · `Agent` re-based on it
- **v0.3** `Crew` API · memory · guardrails · OpenTelemetry tracing · cost tracking
- **v0.4** TypeScript port from the shared spec · MCP *server* mode (`nobelagentic serve --mcp`) · tool registry (`nobelagentic add tool/weather`)

## Layout

```
nobelagentic/
  agent.py        the ReAct loop + handoffs
  tools.py        @tool → JSON schema
  types.py        provider-neutral messages & events
  providers/      anthropic.py, openai_compat.py (OpenAI, Gemini, Ollama, Groq, OpenRouter, Together)
  packs/          built-in tool packs
  mcp.py          MCP client + registry
  cli.py
tests/            runs offline with a scripted FakeProvider
examples/
```

## Run tests

```bash
pytest
```
