Metadata-Version: 2.5
Name: merona-guard
Version: 0.1.0
Summary: Check an x402 seller wallet with merona before your agent pays it. Free, no key.
Project-URL: Homepage, https://merona.io
Project-URL: API, https://api.merona.io
Author-email: merona <hello@merona.io>
License-Expression: MIT
Keywords: agent,crewai,langchain,mcp,merona,payments,trust,x402
Requires-Python: >=3.9
Provides-Extra: crewai
Requires-Dist: crewai>=0.30; extra == 'crewai'
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == 'dev'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.2; extra == 'langchain'
Description-Content-Type: text/markdown

# merona-guard

**Check an x402 seller before your agent pays it.** One call, in your buy loop:
`check → decide → pay`. Backed by [merona](https://merona.io), the independent
x402 settlement index. Free, no key, no signup.

```bash
pip install merona-guard
```

Zero runtime dependencies (stdlib only). The framework adapters below pull in
LangChain / CrewAI only if you use them.

## The buy loop

```python
from merona_guard import Guard

guard = Guard()                                  # free, no key

r = guard.check(seller_wallet, chain="base")
if r.allow:
    pay(seller_wallet, amount)                    # merona: PASS
elif r.review:
    log(r.explain()); maybe_ask_a_human()         # merona: UNCERTAIN
else:
    skip(r.explain())                             # merona: FAIL
```

Prefer it to raise? Gate the payment directly:

```python
from merona_guard import Guard, MeronaBlocked

guard = Guard()
try:
    guard.require(seller_wallet)                   # raises unless ALLOW
    pay(seller_wallet, amount)
except MeronaBlocked as e:
    skip(str(e))                                   # e.g. "merona: DENY — a paid
                                                    # probe recorded a settled
                                                    # payment with no content…"
```

## The one decision that's yours: UNCERTAIN

merona answers **PASS**, **FAIL**, or **UNCERTAIN** — and it returns UNCERTAIN
honestly when it has no evidence, rather than inventing a score. What your
agent does with UNCERTAIN is a risk call only you can make:

```python
from merona_guard import Guard, Policy, DENY, ALLOW

# fail-closed: only ever pay sellers merona has verified
Guard(policy=Policy(on_uncertain=DENY))

# fail-open: pay unless merona actively says FAIL
Guard(policy=Policy(on_uncertain=ALLOW))

# default: REVIEW — hand it back to you / the agent to decide
Guard()
```

If **merona itself is unreachable**, the result is an UNCERTAIN flagged
`available=False`; by default it follows your UNCERTAIN stance, and never
silently flips to ALLOW. A provider hiccup will not crash your buy loop and
will not quietly wave a payment through:

```python
Guard(policy=Policy(on_uncertain=ALLOW, on_unavailable=DENY))
# fail-open on real UNCERTAIN, but fail-closed if merona is down
```

## LangChain

```python
from merona_guard import as_langchain_tool
tool = as_langchain_tool()          # a StructuredTool your agent can call
agent = create_react_agent(llm, [tool, ...])
```

## CrewAI

```python
from merona_guard import as_crewai_tool
agent = Agent(role="buyer", tools=[as_crewai_tool()], ...)
```

Both adapters wrap the same `Guard`, so they share your policy and cache. The
tool returns merona's recorded-fact reason, so a model reasoning over it reads
*"a paid probe recorded a settled payment with no content returned"* — never a
slur about the seller.

## MCP

merona already runs an MCP server, so an MCP-native agent doesn't need this
package at all — point your MCP client at merona's endpoint and call the
`trust_score` / `payto_check` tools directly:

```
https://api.merona.io/mcp        # streamable-HTTP MCP; four tools, all free
```

Use `merona-guard` when you want the check *wrapped in a policy and cache*
inside a Python buy loop; use the MCP tools when the agent orchestrates its own
calls.

## What it does and doesn't do

- **Caches** each verdict for its TTL (merona issues ~6h), so a tight loop
  hitting the same seller doesn't re-call. Unreachable results are never
  cached — they're retried.
- **Never fabricates** a verdict and **never raises** into your buy loop on a
  network error (that becomes an UNCERTAIN your policy decides on).
- **Phones nothing home** beyond the `/v1/trust/evaluate` call you ask for. No
  key, no account, no telemetry.
- merona is an **independent** index — it runs no payment rails and holds no
  seller relationships. Its verdicts are signed and recomputable from public
  on-chain data.

Contact / issues: hello@merona.io · https://merona.io
