# restate-agent

Restate-backed, Pydantic-typed agent runner inspired by PydanticAI's `TemporalAgent`.

## Quickstart

```python
from pydantic import BaseModel
from restate_agent import RestateAgent

class Answer(BaseModel):
    text: str

class DummyAgent:
    async def run(self, prompt: str, deps=None, tools=None) -> Answer:
        return Answer(text=f"Echo: {prompt}")

agent = RestateAgent(DummyAgent(), output_type=Answer)
result = await agent.run("hello")
print(result.text)
```

## Agent contract

`RestateAgent` expects a runner with this shape:

```python
async def run(self, prompt: str, *, deps=None, tools=None) -> OutputT: ...
```

The agent is responsible for using the registered tools (if any) and returning
the output type you pass to `RestateAgent`.

## Durable execution

Durable execution uses an activity executor (e.g., Restate workflow context) to
run the non-deterministic agent call in an activity while keeping orchestration
deterministic.

```python
from restate_agent import RestateAgent
from restate_agent.runtime import RestateActivityExecutor, create_durable_runtime

# ctx is your Restate workflow context
runtime, handler = create_durable_runtime(
    agent,
    lambda _handler: RestateActivityExecutor(ctx),
)
# handler is the activity entrypoint you register with Restate
result = await agent.run("hello", runtime=runtime)
```

## Optional integrations

- `restate` SDK: `pip install "restate-agent[restate]"`

See `docs/` and `examples/` for more detailed usage.

## Build & test

```bash
python -m pip install -e .[restate]
python -m pytest
python -m build
basedpyright
```

## Notes

TemporalAgent compatibility: this library mirrors PydanticAI's `TemporalAgent`
ergonomics but maps workflows/activities to Restate and uses
`create_durable_runtime(...)` to wire the activity boundary.

Durable execution expects JSON-serializable `deps`, tool payloads, and outputs.
