# iknowhy

Python SDK for [iKnowhy.ai](https://iknowhy.ai) — the causal event intelligence platform.

Log every decision, tool call, and outcome your AI agent makes. Trace exactly why things happened. Surface violations. Build the audit trail automatically.

```bash
pip install iknowhy
```

---

## Claude Integration — One-Time Setup

iKnowhy natively integrates with **Claude Code**, **Claude Desktop**, and **Claude.ai**. After a single setup command, every Claude session logs causal events automatically — no prompting, no manual tool calls.

### Step 1 — Get your API key

Sign up at [iknowhy.ai](https://iknowhy.ai) → account dashboard → copy your `cwy_...` key.

### Step 2 — Run setup

```bash
pip install iknowhy
iknowhy setup --key cwy_your_key_here
```

That's it. The setup command:

- ✅ **Claude Code** — registers iKnowhy as an MCP server in `~/.claude/mcp.json` and writes auto-logging instructions to `~/.claude/CLAUDE.md`. Every `claude` session from this point forward logs automatically.
- ✅ **Claude Desktop** — patches `claude_desktop_config.json` with the MCP server. Restart Desktop to activate.
- 📋 **Claude.ai (web)** — prints a ready-to-paste system prompt + connector URL for a one-time Project setup (see below).

### Claude.ai Setup (one time)

Claude.ai custom connectors require a **Pro, Max, Team, or Enterprise** plan.

1. Go to [claude.ai](https://claude.ai) → **Projects** → New Project
2. Project Settings → **Custom Instructions** → paste the system prompt printed by `iknowhy setup`
3. Project Settings → **Connectors** → Add connector:
   - **Name:** `iKnowhy`
   - **URL:** `https://iknowhy.ai/mcp?key=cwy_your_key`
4. Enable the connector via the `+` button in any conversation in this project

Every conversation in this project auto-logs from that point forward.

> **Free tier:** Claude.ai connectors are not available on the free plan. Claude Code and Claude Desktop work on all plans.

---

## MCP Server

iKnowhy runs a live remote MCP server at:

```
https://iknowhy.ai/mcp?key=cwy_your_key
```

Compatible with any MCP client (Claude Code, Claude Desktop, Claude.ai, and any app supporting MCP Streamable HTTP transport).

### Tools exposed

| Tool | Description |
|------|-------------|
| `new_session` | Start a named causal session. Returns `session_id`. |
| `log_event` | Log a causal event with `name`, `session_id`, `payload`, `cause_ids`, `tags`. |
| `get_sessions` | List recent sessions with event counts and durations. |
| `get_chain` | Trace the full causal ancestry of any event. |
| `get_violations` | Check for broken causal rules (e.g. tool_call with no tool_result). |

### Manual MCP registration (without the setup CLI)

**Claude Code:**
```bash
# Add to ~/.claude/mcp.json
{
  "mcpServers": {
    "iknowhy": {
      "type": "http",
      "url": "https://iknowhy.ai/mcp?key=cwy_your_key"
    }
  }
}
```

**Claude Desktop** — add to `claude_desktop_config.json`:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- Linux: `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "iknowhy": {
      "type": "http",
      "url": "https://iknowhy.ai/mcp?key=cwy_your_key"
    }
  }
}
```

---

## Python SDK

For direct API access — log events from your own code, scripts, or agents.

```python
from iknowhy import CausewayClient

client = CausewayClient(api_key="cwy_...")

# Start a session
session_id = "my-session-001"

# Log a causal chain
req  = client.log("user_request",  payload={"task": "analyze logs"},  session_id=session_id)
dec  = client.log("decision",      payload={"action": "run scan"},    session_id=session_id, cause_ids=[req])
call = client.log("tool_call",     payload={"tool": "scanner"},       session_id=session_id, cause_ids=[dec])
res  = client.log("tool_result",   payload={"findings": 3},           session_id=session_id, cause_ids=[call])
done = client.log("task_complete", payload={"status": "ok"},          session_id=session_id, cause_ids=[res])

# Trace why something happened
chain = client.chain(done)
for event in chain:
    print(event["name"], "←", event.get("cause_ids", []))

# Check for violations
violations = client.violations()
print(f"{len(violations)} constraint violations found")
```

### `CausewayClient` reference

```python
CausewayClient(api_key: str, base_url: str = "https://iknowhy.ai")
```

| Method | Returns | Description |
|--------|---------|-------------|
| `log(name, payload, session_id, cause_ids, tags)` | `str` (event_id) | Log a causal event |
| `chain(event_id)` | `list[dict]` | Full causal ancestry for an event |
| `violations(session_id)` | `list[dict]` | Constraint violations |
| `sessions(limit)` | `list[dict]` | Recent sessions |
| `events(session_id, name, limit)` | `list[dict]` | Query events |

---

## Standard Event Types

Use consistent names to get the most out of iKnowhy's causal analysis:

| Event Name | When to use |
|-----------|-------------|
| `user_request` | User sends a message or task |
| `decision` | Agent chooses an approach |
| `tool_call` | Before calling any tool |
| `tool_result` | After receiving a tool result |
| `error` | Any failure or exception |
| `error_handling` | Recovery from an error |
| `external_send` | Sending output to external system |
| `task_complete` | Task finished |

Always chain them: `tool_result` should have `cause_ids=[tool_call_id]`.

---

## PyRapide Integration

iKnowhy integrates natively with **[PyRapide](https://pypi.org/project/pyrapide/)**, the causal event-driven architecture library by [Shane Morris](https://github.com/ShaneDolphin).

```bash
pip install iknowhy pyrapide
```

### Batch mode

```python
from iknowhy import CausewayClient
from iknowhy.pyrapide import PyRapideAdapter

client = CausewayClient(api_key="cwy_...")
adapter = PyRapideAdapter(client, session_id="security-scan-001")

comp = await engine.run(arch, timeout=5.0)
event_ids = await adapter.flush_computation(comp)
print(f"Logged {len(event_ids)} events to iKnowhy")
```

### Streaming mode

```python
adapter = PyRapideAdapter(client, session_id="live-monitor")
adapter.attach_stream(processor, session_id="live-monitor")
# Events flow to iKnowhy in real time as they pass through PyRapide
```

### `PyRapideAdapter` reference

| Method | Description |
|--------|-------------|
| `flush_computation(comp, session_id, tags)` | Upload a completed PyRapide `Computation` |
| `attach_stream(processor, session_id, tags)` | Hook into a live `StreamProcessor` |
| `id_map()` | PyRapide event.id → iKnowhy event_id mapping |
| `clear()` | Reset ID map between computations |

> PyRapide by **Shane Morris** — [github.com/ShaneDolphin/pyrapide](https://github.com/ShaneDolphin/pyrapide) · [pypi.org/project/pyrapide](https://pypi.org/project/pyrapide/)

---

## Links

- [iKnowhy Dashboard](https://iknowhy.ai)
- [Full API Docs](https://iknowhy.ai/docs-guide)
- [GitHub](https://github.com/bytecreeper/iknowhy-sdk)
- [PyRapide](https://pypi.org/project/pyrapide/) — by Shane Morris
