# Examples

This repo includes runnable examples under `../src/examples/`.

## End-to-end tool-calling loop

Based on: `../src/examples/basic.py`

What it demonstrates:
- Defining tools with `@registry.tool()`
- Running `ToolRunner.run(...)` until the model returns final text
- Returning tool results as JSON strings via `function_call_output`

Minimal version:

```python
import os
from typing import Dict

from openai import OpenAI

from openai_resptools import ToolRegistry, ToolRunner

store: Dict[str, str] = {}
registry = ToolRegistry()


@registry.tool()
def write(key: str, text: str) -> dict:
    store[key] = text
    return {"ok": True, "key": key, "length": len(text)}


@registry.tool()
def read(key: str) -> dict:
    return {"key": key, "text": store.get(key)}


client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

runner = ToolRunner(
    client,
    model=os.getenv("OPENAI_MODEL", "gpt-4o-mini"),
    registry=registry,
    max_iters=6,
    parallel_tool_calls=False,
)

result = runner.run(
    "Do the following steps using tools:\n"
    "1) Call write to save the text 'Hello from tools!' under key 'greeting'.\n"
    "2) Call read for key 'greeting'.\n"
    "3) Reply with ONLY the value of the text you read.\n"
)

print(result.text)
```

## Registry patterns

Based on: `../src/examples/registry_patterns.py`

### Pattern 1: Registry as a class (auto-register public methods)

```python
from openai_resptools import ToolRegistry


class MyServiceTools(ToolRegistry):
    def __init__(self, db_conn: str) -> None:
        super().__init__()
        self.db_conn = db_conn

    def get_user_status(self, user_id: int) -> str:
        return f"User {user_id} is active (DB: {self.db_conn})"


service = MyServiceTools(db_conn="postgres://localhost:5432")
print(service.names())
```

### Pattern 2: Manual dispatch (no ToolRunner)

```python
import json

from openai_resptools import ToolRegistry

registry = ToolRegistry()


@registry.tool()
def calculator(a: int, b: int, op: str) -> int:
    if op == "+":
        return a + b
    if op == "-":
        return a - b
    raise ValueError(f"Unsupported operation: {op!r}")


mock_call = {"name": "calculator", "arguments": '{"a": 10, "b": 5, "op": "+"}'}
args = json.loads(mock_call["arguments"])
output = registry.get(mock_call["name"]).call(args)
print(output)
```

