Metadata-Version: 2.4
Name: obz-neo-sdk
Version: 0.1.8
Summary: Neo SDK with integrated telemetry
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: urllib3>=2.0.0
Requires-Dist: opentelemetry-api<2,>=1.28.0
Requires-Dist: opentelemetry-sdk<2,>=1.28.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http<2,>=1.28.0
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc<2,>=1.28.0
Requires-Dist: opentelemetry-instrumentation-logging>=0.55b1
Requires-Dist: opentelemetry-instrumentation-requests>=0.55b1
Requires-Dist: opentelemetry-instrumentation-sqlalchemy>=0.55b1
Requires-Dist: opentelemetry-instrumentation-threading>=0.55b1
Requires-Dist: colorama<0.5,>=0.4.6
Requires-Dist: tenacity<10.0,>=8.2.3
Requires-Dist: jinja2<4,>=3.1.5
Requires-Dist: deprecated<2,>=1.2.14
Requires-Dist: posthog<4,>3.0.2
Requires-Dist: aiohttp<4,>=3.10.5

# Neo SDK

Python SDK for **Neo GenAI Studio**: create agents, load workspace tools, save conversations, and send traces to Langfuse.

---

## What you can do

- Sign in with an **M2M API key** (machine-to-machine key from GenAI Studio)
- Read your **workspace** and create or delete **agents**
- Load **custom tools** from the workspace as LangChain tools
- Publish a **custom agent** to Studio with ``@studio_agent``
- Send **OpenTelemetry traces** (optional, via StudioTelemetry)

---

## Requirements

| Item | Version |
|------|---------|
| Python | 3.7+ for the SDK only |
| pip or uv | latest |

For the [custom agent example](examples/custom_agent_service/), use **Python 3.11 or 3.12**.

---

## Install

### Option A — From this repo (development)

```bash
git clone <repository-url>
cd Neo-SDK
pip install -e .
```

This installs the distribution **`obz-neo-sdk`** (import package `neo`) from this repo.

### Option B — From AWS CodeArtifact or PyPI (published package)

The install name is **`obz-neo-sdk`** (`neo-sdk` is already taken on PyPI). Imports stay `from neo import ...`.

```bash
pip install obz-neo-sdk
```

If your team publishes to CodeArtifact, authenticate with your org’s token and index URL, then install `obz-neo-sdk`. The custom agent example uses an editable monorepo path by default; switch `tool.uv.sources` in `examples/custom_agent_service/pyproject.toml` to the published index when needed.

### Check it works

```bash
python -c "from neo import NeoSDK; print('OK')"
```

---

## Quick start

You need two values from GenAI Studio:

1. **Host** — your builder URL (e.g. `https://botbuilder.your-company.com` or `http://localhost:3030`)
2. **API key** — Settings → API Keys → **Create M2M Key**

```python
from neo import NeoSDK

client = NeoSDK(
    host="https://botbuilder.your-company.com",
    api_key="your-m2m-api-key",
)

workspace = client.get_workspace()
print(workspace["name"])
print("Workspace ID:", client.workspace_id)

agent = client.create_agent(name="My Agent")
print("Agent ID:", agent.id)

client.delete_agent(agent.id)
```

### Running against localhost

When `NEO_HOST` is `localhost` or `127.0.0.1`, you must also pass the **flows** service URL (agentic-flow API):

```python
client = NeoSDK(
    host="http://localhost:3030",
    api_key="your-m2m-api-key",
    flows_host="http://localhost:7860",  # or set env NEO_FLOWS_HOST
)
```

On hosted URLs (e.g. `botbuilder.*`), the SDK derives the flows host automatically.

---

## Environment variables (scripts and notebooks)

```bash
export NEO_HOST="https://botbuilder.your-company.com"
export NEO_API_KEY="your-m2m-api-key"
# Local only:
export NEO_FLOWS_HOST="http://localhost:7860"
```

Never commit real keys. Use env vars or a local `.env` file.

---

## API overview

### `NeoSDK(host, api_key, flows_host=None, timeout=30, max_retries=3)`

| Method / property | What it does |
|-------------------|--------------|
| `get_workspace()` | Workspace name, id, plan, etc. |
| `workspace_id` | Cached workspace id |
| `create_agent(name, description="", tags=None, mcp_enabled=True)` | Creates an agentic flow (folder is handled for you) |
| `delete_agent(agent_id)` | Deletes an agent |
| `get_tools(tool_names=None)` | Workspace tools as LangChain `StructuredTool` list |
| `tools` | Lower-level `CustomTools` API |
| `save_conversation(session_id, user_message, agent_message)` | Persist one turn to GenAI Studio |
| `complete_session(session_id)` | Mark session complete |
| `llmops_token`, `user_id`, `user_email` | For telemetry (fetched at init) |

### Errors

```python
from neo import AuthenticationError, HTTPClientError

try:
    client = NeoSDK(host="...", api_key="bad-key")
except AuthenticationError:
    print("Check host and API key")

try:
    client.get_workspace()
except HTTPClientError as e:
    print(e.status_code, e)
```

The client retries on rate limits (429) and server errors (5xx) with exponential backoff.

---

## Custom agents (published package)

Decorate your agent class. When the HTTP service starts with `NEO_HOST` and `NEO_M2M_API_KEY`, Neo SDK creates (or reuses) a Studio Remote Agent.

```python
from neo import studio_agent
from neo.services.custom_agent.entrypoint import main as run_service

@studio_agent()  # name/description from agent.json; url from NEO_AGENT_URL or localhost:{port}/run
class HelpdeskAgent:
    ...

if __name__ == "__main__":
    run_service(agent_class=HelpdeskAgent)
```

Optional kwargs: `name=`, `description=`, `url=`. Set `NEO_AGENT_ID` to skip create and reuse an existing UUID. The same traces and conversations work without the decorator if you supply that UUID (Studio UI or `/run` `agent_id`).

Full decorator, startup, `/run`, collector flow, and agents that are not registered via `@studio_agent`: [docs/custom-agent-flow.md](docs/custom-agent-flow.md).

---

## Telemetry (optional)

```python
from neo import NeoSDK, set_association_properties
from studiotelemetry import StudioTelemetry

client = NeoSDK(host="...", api_key="...")
agent = client.create_agent(name="My Agent")

StudioTelemetry.init(
    api_endpoint="https://your-collector/api/public/otel",
    app_name="my-app",
)

set_association_properties(agent.id, client)
# Your LLM / LangGraph code here — calls are traced when instrumented
```

See [examples/03_telemetry.ipynb](examples/03_telemetry.ipynb) and [examples/README.md](examples/README.md).

---

## Examples

| Resource | Description |
|----------|-------------|
| [examples/01_authentication_and_workspace.ipynb](examples/01_authentication_and_workspace.ipynb) | Auth and workspace |
| [examples/02_agent_management.ipynb](examples/02_agent_management.ipynb) | Create and delete agents |
| [examples/03_telemetry.ipynb](examples/03_telemetry.ipynb) | Tracing with StudioTelemetry |
| [examples/custom_agent_service/](examples/custom_agent_service/) | Production LangGraph HTTP service |

```bash
pip install -e .
pip install jupyter
export NEO_HOST="..." NEO_API_KEY="..."
jupyter notebook examples/
```

---

## Custom agent service

Ready-made **FastAPI + LangGraph** template that GenAI Studio calls over HTTP:

- Endpoints: `/health`, `/run`, `/info`, `/complete`
- Loads workspace tools (filtered by `agent.json`)
- Traces to Langfuse; saves conversations when `NEO_M2M_API_KEY` is set

**Setup:** [examples/custom_agent_service/README.md](examples/custom_agent_service/README.md)

**Build your own service from scratch:** [examples/custom_agent_service/README_SETUP_FROM_SCRATCH.md](examples/custom_agent_service/README_SETUP_FROM_SCRATCH.md)

---

## Project layout

```
Neo-SDK/
├── neo/                    # SDK (client, tools, custom agent framework)
├── studiotelemetry/        # OpenTelemetry / StudioTelemetry (monorepo)
├── examples/               # Notebooks + custom_agent_service
└── pyproject.toml
```

---

## Troubleshooting

| Problem | What to try |
|---------|-------------|
| `AuthenticationError` | Correct `host` and M2M key; key created in the same workspace |
| `No workspace_id available` | API key permissions; `get_workspace()` failed at init |
| Agent create/delete fails on localhost | Set `flows_host` or `NEO_FLOWS_HOST` to agentic-flow URL |
| Request timeout | `NeoSDK(..., timeout=60)` |
| Import `studiotelemetry` fails | Telemetry is optional for basic SDK use; install from monorepo if needed |

---

## Version

Current package version: **0.1.8** (see `neo/_version.py`).

---

## License

All rights reserved by OneByZero AI.

For help, contact the Neo / GenAI Studio team.
