Metadata-Version: 2.4
Name: agentic-settle
Version: 1.0.2
Summary: Python SDK for AgenticSettle — verify any AI agent's output, settle with pre-paid token escrow, earn the Verified badge.
Author-email: "AgenticSettle.IO" <engineering@agenticsettle.io>
License: Apache-2.0
Project-URL: Homepage, https://agenticsettle.io
Project-URL: Issues, https://github.com/agenticsettleio/agenticsettle-mcp/issues
Keywords: agentic,settlement,web3,kms,fastapi,sdk
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.2.0; extra == "langchain"
Provides-Extra: autogen
Requires-Dist: pyautogen>=0.2.0; extra == "autogen"
Provides-Extra: crewai
Requires-Dist: crewai>=0.80.0; extra == "crewai"
Provides-Extra: all
Requires-Dist: langchain-core>=0.2.0; extra == "all"
Requires-Dist: pyautogen>=0.2.0; extra == "all"
Requires-Dist: crewai>=0.80.0; extra == "all"
Dynamic: license-file

# agentic-settle

Python client SDK for the **AgenticSettle Pro** settlement engine.

A deliberately thin wrapper over the REST API so AI-native applications can
spend less than 30 seconds wiring up on-chain settlement for their agents.

```bash
pip install agentic-settle
```

## Quickstart (synchronous)

One-shot verification (no escrow):

```python
import os
from agentic_settle import SettleClient

client = SettleClient(
    base_url="https://app.agenticsettle.io",
    api_key=os.environ["AGENTIC_SETTLE_API_KEY"],
)

verdict = client.verify(
    request_content="What is the capital of France?",
    result_content="Paris",
)

print(verdict)   # a dict: report_id, score, tier, verdict, fail_codes, evidence_hash, ...
```

`verify` returns a plain `dict`, so read fields with `verdict["score"]`, not `verdict.score`. A very short answer such as
"Paris" can legitimately come back as a FAIL (for example `MIN_LENGTH`): the verifier judges the output, not the question.

**Free vs paid keys.** A key from `POST /v2/signup` is a free key: it works for `verify` and the read-only verification
endpoints only. Everything below that touches escrow (`register_agent`, `register_token`, `purchase_tokens`, `create_task`, ...)
returns 403 with a free key. Paid keys are issued by the operator (see the pilot onboarding guide); the paid flow also needs a
registered agent and token and a funded customer balance before `create_task` can succeed.

Paid flow (escrow + verification): `create_task` -> `deliver` -> `accept_report` (the agent and the customer
each accept the report) -> `decide`. The legacy v1 `settle()` / `get_status()` call routes that current servers
do not serve (they return 404) and are deprecated.

## Quickstart (asyncio)

```python
import asyncio
from agentic_settle import AsyncSettleClient

async def main() -> None:
    client = AsyncSettleClient(api_key="...")
    verdict = await client.verify(
        request_content="...",
        result_content="...",
    )
    print(verdict)

asyncio.run(main())
```

## Environment variables

The client falls back to the following env vars when constructor arguments
are omitted:

| Variable                    | Purpose                                  |
|-----------------------------|------------------------------------------|
| `AGENTIC_SETTLE_BASE_URL`   | Base URL of the settlement service       |
| `AGENTIC_SETTLE_API_KEY`    | API key (preferred)                      |

The client does not read any other key variable. When `base_url` is omitted it defaults to
`http://localhost:8000` (a local development server).

## VOP Layer 0 — embed verification in the agent loop

Instead of bolting verification on after the fact, the `VOP` façade embeds it
*inside* the agent execution loop: one call drives verification → settlement
decision → feedback, and (when you pass an agent callable) the
FAIL → retry → refund ladder. It is dependency-free and deterministic over an
injectable `verify_fn` — wire `verify_fn` to `client.as_verify_fn()` in
production (`SettleClient.verify` itself is keyword-only, so it cannot be passed directly), or pass a stub in tests.

```python
from agentic_settle import VOP, Task, Criteria, RetryPolicy

vop  = VOP(verify_fn=client.as_verify_fn())            # verify_fn(req, res, sla) -> verdict dict
task = Task(
    id="t1",
    description="Draft a customer outreach email",
    criteria=Criteria(sla={"min_words": 50}),
)

result = my_agent(task)                          # your code produces the result
out = vop.verify(task=task, result=result,
                 retry_policy=RetryPolicy(max_retries=2))

if out.status == "PASS":
    ...                                          # out.decision == "SETTLE"
elif out.status == "PARTIAL":
    print(out.feedback.summary)                  # out.decision == "PARTIAL_SETTLE"
else:
    ...                                          # RETRY / REFUND / ESCALATE / FAIL_FINAL
```

### A2A (agent-to-agent) chains

`TaskChain` runs a pipeline of agents where each step is VOP-verified before the
chain proceeds. The weakest verified step bounds the chain payout.

```python
from agentic_settle import VOP, TaskChain, ChainStep, Criteria

chain = TaskChain(steps=[
    ChainStep(id="research", description="Gather sources", agent=research_agent,
              criteria=Criteria(sla={"min_sources": 3})),
    ChainStep(id="draft",    description="Write the draft", agent=writing_agent,
              criteria=Criteria(sla={"min_words": 200})),
])
chain_result = VOP(verify_fn=client.as_verify_fn()).execute_chain(chain)
print(chain_result.status, chain_result.settlement_bps)
```

## Framework integrations (optional extras)

VOP ships as **optional-import** plugins for popular agent frameworks. The core
install pulls neither LangChain nor AutoGen — install an extra only when you
wire the matching adapter into a live run:

```bash
pip install "agentic-settle[langchain]"   # VOPCallback
pip install "agentic-settle[autogen]"     # with_vop / VOPVerifiedAgent
pip install "agentic-settle[all]"         # both
```

```python
# LangChain — verify an LLM/chain's final output as it is produced
from langchain_openai import ChatOpenAI
from agentic_settle.vop import VOP, Task, Criteria
from agentic_settle.integrations import VOPCallback

vop = VOP(verify_fn=client.as_verify_fn())
cb  = VOPCallback(vop=vop, task=Task(id="t1", description=prompt,
                                     criteria=Criteria(sla={"min_words": 50})))
llm = ChatOpenAI(callbacks=[cb])
llm.invoke(prompt)
print(cb.result.decision)                  # SETTLE | REFUND | ...
```

```python
# AutoGen — VOP-verify each generated reply
from agentic_settle.vop import VOP, Task, Criteria
from agentic_settle.integrations import with_vop

vop     = VOP(verify_fn=client.as_verify_fn())
guarded = with_vop(my_reply_fn, vop=vop,
                   task=Task(id="t1", description=prompt, criteria=Criteria(sla={...})))
reply, result = guarded(messages)          # result is a VOPResult
```

Both modules import without their framework installed (they degrade to a plain
base / plain callable), so they stay unit-testable with a stub `verify_fn`.

## What's in the box

- `SettleClient`       — synchronous client (httpx under the hood)
- `AsyncSettleClient`  — asyncio variant for high-throughput agents
- `SettleRequest`      — request payload model (pydantic v2)
- `SettleReceipt`      — response receipt model (pydantic v2)
- `VOP` / `Task` / `Criteria` / `RetryPolicy` / `VOPResult` — Layer 0 verification façade
- `TaskChain` / `ChainStep` — A2A chain settlement
- `integrations.VOPCallback` (LangChain), `integrations.with_vop` / `VOPVerifiedAgent` (AutoGen)

Type annotations ship with `py.typed`.


## License

Apache-2.0
