Metadata-Version: 2.4
Name: tinkerfin-agui-adapter
Version: 0.1.0
Summary: Deep Agents v2 stream conversion for AG-UI.
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/tinkerfin-ai/tinkerfin
Project-URL: Repository, https://github.com/tinkerfin-ai/tinkerfin
Project-URL: Issues, https://github.com/tinkerfin-ai/tinkerfin/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: ag-ui-protocol==0.1.19
Requires-Dist: langchain-core<2,>=1.5.3
Requires-Dist: pydantic<3,>=2
Requires-Dist: pydantic-core<3,>=2
Dynamic: license-file

# TinkerFin AG-UI Adapter

## What it is

`tinkerfin-agui-adapter` converts caller-owned Deep Agents or LangGraph v2 stream
parts into validated AG-UI 0.1.19 events. It does not create a graph, query
checkpoints, authenticate requests, or provide HTTP routes.

Use it when an application already owns graph execution and only needs protocol
conversion. Applications that need Agent installation, execution scope, checkpoint
access, and SSE can use [`tinkerfin`](../tinkerfin/README.md).

## Installation

Python 3.11 or newer is required. The package is not published to PyPI. From the
repository root, install the locked workspace:

```bash
uv sync --all-packages --locked
```

## Quick Start

The converter accepts an asynchronous iterable of v2 parts. This minimal stream is
self-contained and does not require Deep Agents or LangGraph at runtime:

<!-- adapter-quick-start:start -->
```python
import asyncio

from langchain_core.messages import AIMessageChunk

from tinkerfin_agui_adapter import astream_events


run_input = {
    "threadId": "thread-1",
    "runId": "run-1",
    "state": {},
    "messages": [{"id": "user-1", "role": "user", "content": "Hello"}],
    "tools": [],
    "context": [],
    "forwardedProps": {},
}


async def parts():
    yield {
        "type": "messages",
        "ns": (),
        "data": (
            AIMessageChunk(id="ai-1", content="Hello", chunk_position="last"),
            {"lc_agent_name": None, "langgraph_node": "model"},
        ),
    }
    yield {"type": "values", "ns": (), "data": {}, "interrupts": ()}


async def main():
    async for event in astream_events(input=run_input, parts=parts()):
        print(event.type.value)


asyncio.run(main())
```
<!-- adapter-quick-start:end -->

Real graph integration should provide live v2 `messages`, `tasks`, and `values`
parts. The adapter pulls with backpressure and closes the upstream iterator on
cancellation or early consumer exit when `aclose()` is available.

## Event contract

- One request emits one `RUN_STARTED` and one main terminal event.
- Text, reasoning, and Tool lifecycles close before state, interrupt, error, or
  completion events.
- Namespaces and protocol IDs correlate concurrent messages, Tool calls, results,
  and subagents; arrival order is not identity.
- Provider-private reasoning is excluded from public payloads.
  `expose_reasoning_events=True` enables only supported reasoning fields.
- `expose_subagent_events=False` still validates subgraph parts while suppressing
  their public events.
- `encode_sse(event, event_id=...)` encodes one event; transport order, delivery,
  retry, and cancellation remain the caller's responsibility.

## License

Apache License 2.0. See [LICENSE](LICENSE).
