Metadata-Version: 2.4
Name: kranth
Version: 0.3.0
Summary: Stress-test ideas with hundreds of AI personas. Adversarial multi-bias debate. API-first.
Project-URL: Homepage, https://kranth.com
Project-URL: Source, https://github.com/VYLTH/kranth-python
Project-URL: Issues, https://github.com/VYLTH/kranth-python/issues
Author-email: Kranth <support@kranth.com>
License: Apache-2.0
Keywords: ai,kranth,personas,simulation,synthetic-audience
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx-sse>=0.4.0
Requires-Dist: httpx>=0.27.0
Description-Content-Type: text/markdown

# Kranth — Python SDK

```bash
pip install kranth
```

```python
from kranth import Kranth

client = Kranth(api_key="kr_live_…")

sim = client.sims.create(
    idea_text="We're launching a paid Rust devtool. $29/mo, hosted, no self-host.",
    persona_count=50,
    model_id="claude-sonnet-4-6",
)

for ev in client.sims.stream(sim.sim_id):
    if ev.kind == "persona.ready":
        print(f"persona {ev.data['persona_id']} ready")
    elif ev.kind == "reaction.complete":
        print(f"  → {ev.data['sentiment']:+.2f} {ev.data['persona_id']}")
    elif ev.kind == "sim.complete":
        report = ev.data.get("report") or {}
        print("verdict:", report.get("sentiment_score"))
        print("objections:")
        for o in report.get("top_objections", []):
            print("  ·", o)
        break
```

## Async

```python
import asyncio
from kranth import AsyncKranth

async def main():
    async with AsyncKranth(api_key="kr_live_…") as client:
        models = await client.models.list()
        sim = await client.sims.create(
            idea_text="…",
            persona_count=50,
            model_id=models[0].id,
        )
        async for ev in client.sims.stream(sim.sim_id):
            print(ev.kind)

asyncio.run(main())
```

## Recon — web-grounded research

A swarm of agents researches your idea on the live web and returns a cited, scored verdict.

```python
recon = client.recon.create(idea_text="Paid Rust devtool, $29/mo", tier="scout")
for ev in client.recon.stream(recon.recon_id):
    if ev.kind == "recon.complete":
        break
detail = client.recon.get(recon.recon_id)
print(detail.run.score, "·", len(detail.findings), "findings", len(detail.sources), "sources")
```

## Debates — adversarial panel

```python
debate = client.debates.create(topic="Should we kill the free tier?", mode="panel")
for ev in client.debates.stream(debate.id):
    if ev.kind == "debate.complete":
        break
d = client.debates.get(debate.id)
print(d.synthesis.score, d.synthesis.summary)
```

## Resources

- `client.sims.create(...)` — submit a sim
- `client.sims.get(sim_id)` — single sim with status + verdict
- `client.sims.list(status=..., cursor=..., limit=...)` — paginated
- `client.sims.stream(sim_id)` — SSE event stream
- `client.sims.cancel(sim_id)` — abort + refund unspent credits
- `client.sims.export(sim_id)` — full report incl. reactions + clusters
- `client.recon.create(idea_text, tier, ...)` / `get` / `list` / `tiers` / `export` / `stream` — web-grounded research
- `client.debates.create(topic, mode, ...)` / `get` / `list` / `turns` / `set_public` / `cancel` / `export` / `stream` — adversarial panel
- `client.api_keys.create(name, env="live"|"test")` — mint
- `client.api_keys.list()` / `client.api_keys.revoke(id)`
- `client.models.list()` — registry (id, tier, credits/100p, plan_min)
- `client.billing.usage()` — credits consumed + remaining
- `client.billing.checkout_url(plan="pro", billing_period="monthly")` — Stripe Checkout URL
- `client.billing.portal_url()` — Stripe Customer Portal URL

## Errors

```python
from kranth import KranthPaymentRequired, KranthRateLimited

try:
    client.sims.create(...)
except KranthPaymentRequired:
    # out of credits — top up via client.billing.checkout_url("pro")
    ...
except KranthRateLimited as e:
    # over RPM — back off for e.retry_after seconds
    ...
```

Full exception tree: `KranthError → KranthAPIError → {KranthAuthError, KranthValidationError, KranthPaymentRequired, KranthRateLimited}`.

## Configuration

```python
client = Kranth(
    api_key="kr_live_…",
    base_url="https://api.kranth.ai",   # default
    timeout=30.0,
)
```

Bring your own `httpx.Client` if you need custom transport (proxies, mTLS, retries):

```python
import httpx
client = Kranth(api_key="…", client=httpx.Client(transport=httpx.HTTPTransport(retries=3)))
```

## License

Apache-2.0
