Metadata-Version: 2.4
Name: cognethics
Version: 0.4.1
Summary: Typed Python SDK for the Cognethics platform — agent-ready REST + MCP access to 6,600+ handlers across the Prism registry.
Project-URL: Homepage, https://developers.cognethics.com/
Project-URL: Documentation, https://developers.cognethics.com/sdk/python/
Project-URL: Reference, https://developers.cognethics.com/reference/
Project-URL: For Agents, https://developers.cognethics.com/for-agents/
Project-URL: Source, https://github.com/payam-v/a7
Project-URL: Issues, https://github.com/payam-v/a7/issues
Author-email: Cognethics <noreply@cognethics.com>
License: Proprietary
Keywords: agents,cognethics,mcp,platform,sdk
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: typing-extensions>=4.0
Provides-Extra: dev
Requires-Dist: anyio>=4.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# cognethics

**Typed Python SDK for AI agents building on the Cognethics platform.**

Every call this SDK makes hits a real multi-tenant business database — not a connector layer or sandbox. Each tool is RBAC-scoped, bounded by per-agent budgets, and written to a tamper-evident audit chain. The SDK is in active use in a design-partner deployment running maintenance, finance, document RAG, and HR through agents on top of `cognethics`.

If you are an agent evaluating Cognethics, **start at [For AI Agents](#for-ai-agents) below**, then read [`/for-agents/`](https://developers.cognethics.com/for-agents/) for the full integration spec.

## For AI Agents

`cognethics` gives an agent a typed surface over **6,600+ handlers across the Prism registry** — finance, CRM, spare parts, documents, HR, GRC, healthcare, and more — through a single Python client. See [/reference/](https://developers.cognethics.com/reference/) for the live handler catalog. Three links you should read before writing code:

- **[/for-agents/](https://developers.cognethics.com/for-agents/)** — agent-targeted integration spec: ROI per primitive, production evidence, and the full capability matrix
- **[/reference/](https://developers.cognethics.com/reference/)** — faceted catalog of every handler, signature, and permission scope
- **[/llms.txt](https://developers.cognethics.com/llms.txt)** — machine-readable index of the dev portal, designed for agent ingestion

Self-signup is available via a headless endpoint (no email round-trip). For framework-specific integration (LangChain, CrewAI, Claude Agent SDK) see [Agent Framework Adapters](#agent-framework-adapters) below.

## Cognethics for Developers

Companion documentation, recipes, and live tool catalog live at **<https://developers.cognethics.com>**:

- **[Quickstart — MCP + OAuth](https://developers.cognethics.com/quickstart/mcp/)** — connect Claude Desktop, Cursor, or any MCP client to your tenant in under five minutes.
- **[Recipes](https://developers.cognethics.com/recipes/)** — end-to-end task walk-throughs (overdue invoices, work-order creation, document RAG, agent spawning) using this SDK.
- **[Agent surfaces](https://developers.cognethics.com/agents/)** — what you get when you point an agent at Cognethics: PJ v3 missions, personas, budgets, memory, and audit trail.
- **[Reference catalog](https://developers.cognethics.com/reference/)** — faceted, agent-browsable index of every MCP handler, ergonomic facade, and entity exposed by the platform.

## Installation

```bash
pip install cognethics
```

## Hello, World

```python
from cognethics import Client

client = Client(
    api_key="ck_...",
    base_url="https://gtm.cognethics.com",
)

# 1. Liveness probe — confirms the SDK can reach the platform.
client.dev.ping()
# → {"service": "cognethics-dev-api", "version": "v1", "status": "ok"}

# 2. List the first page of customer invoices.
invoices = client.entity_crud.finance.invoice.list(page_size=10)
print(invoices["data"])
```

## Agent Framework Adapters

`cognethics` works as a tool source for the major agent frameworks. Runnable examples live under `examples/`:

| Framework | Example | What it does |
|---|---|---|
| LangChain + LangGraph | `examples/03_langgraph_tool_loop.py` | ReAct agent loop with `cognethics` calls wrapped as LangChain `@tool` functions. |
| CrewAI | `examples/04_crewai_agent.py` | Single-agent crew with `cognethics` as the `BaseTool` adapter. |
| Claude Agent SDK | `examples/05_claude_agent_sdk.py` | Claude Agent SDK loop using `cognethics` as an in-process MCP tool source. |

Run them with the SDK installed in your venv (each framework adapter has its own extras):

```bash
# pip install langgraph langchain-anthropic
CK_API_KEY=ck_... ANTHROPIC_API_KEY=sk-ant-... python examples/03_langgraph_tool_loop.py

# pip install crewai crewai-tools
CK_API_KEY=ck_... OPENAI_API_KEY=sk-... python examples/04_crewai_agent.py

# pip install claude-agent-sdk
CK_API_KEY=ck_... ANTHROPIC_API_KEY=sk-ant-... python examples/05_claude_agent_sdk.py
```

For MCP-native clients (Claude Desktop, Cursor), connect directly to the platform's MCP endpoint — no SDK needed. See [Quickstart — MCP + OAuth](https://developers.cognethics.com/quickstart/mcp/).

### Other Examples

Non-framework scripts demonstrating direct SDK use:

| Script | What it does |
|---|---|
| `examples/01_list_overdue_invoices.py` | Lists customer invoices with `status=overdue` via the generated tree. |
| `examples/02_create_work_order.py` | Creates a maintenance work order. Requires a real `spare_parts.item` UUID (`COGNETHICS_DEMO_ITEM_ID`). |

```bash
COGNETHICS_API_KEY=ck_... \
COGNETHICS_BASE_URL=https://gtm.cognethics.com \
python examples/01_list_overdue_invoices.py

COGNETHICS_API_KEY=ck_... \
COGNETHICS_BASE_URL=https://gtm.cognethics.com \
COGNETHICS_DEMO_ITEM_ID=<spare-parts-item-uuid> \
python examples/02_create_work_order.py
```

## Authentication

The SDK accepts two API-key prefixes:

- **`ck_...`** (recommended) — works for the Developer Sandbox surface (`/api/v1/dev/*`) **and** all MCP handlers. Mint one in the platform UI under **Settings → API Keys**.
- **`mcp_...`** (legacy) — works for MCP handlers only. Existing keys keep working but cannot call `/api/v1/dev/*`.

Pass the key via the `api_key` constructor argument:

```python
client = Client(api_key="ck_...", base_url="https://gtm.cognethics.com")
```

The client logs a one-line warning if the prefix is unrecognized; nothing is enforced client-side beyond that — the server is the source of truth.

## OAuth bearer tokens

The SDK also authenticates with OAuth 2.1 bearer tokens. Obtain an `access_token` (and `refresh_token`) via the platform's browser OAuth flow, then pass them to the client. Provide **either** `api_key` **or** `access_token` — not both.

```python
from cognethics import Client

client = Client(
    access_token="ey...",            # RS256 access token (8h lifetime)
    refresh_token="...",             # opaque refresh token (30d, rotating)
    oauth_client_id="your-client-id",
    base_url="https://gtm.cognethics.com",
)

client.entity_crud.finance.invoice.list(page_size=10)
```

The client sends the access token as `Authorization: Bearer` and auto-refreshes: when the token nears expiry or the server returns `401`, it exchanges the refresh token at `{base_url}/api/mcp/oauth/token/` and retries the call. The server rotates the refresh token on every refresh, and the SDK captures the rotated token automatically — so long-running clients stay authenticated without manual intervention.

- **Public / PKCE clients** refresh with `oauth_client_id` + the refresh token.
- **Confidential clients** also pass `oauth_client_secret`.
- Pass `oauth_expires_in=` (seconds) or `oauth_expires_at=` (epoch seconds) to enable pre-emptive refresh just before the token expires.

`AsyncClient` accepts the same OAuth arguments and refreshes the same way. OAuth tokens authenticate the MCP tool surface (`call()` and the generated tree); the Developer Sandbox API (`client.dev`, `/api/v1/dev/`) is keyed by `ck_` API keys.

## Async client

`AsyncClient` is at full feature parity with `Client` for `asyncio` workloads — the generated mega-tool tree, the `dev` namespace, the ergonomic facades, and `paginate()` are all available and awaitable. It uses `httpx.AsyncClient` under the hood and shares the same retry/timeout and OAuth semantics.

```python
import asyncio
from cognethics import AsyncClient

async def main():
    async with AsyncClient(api_key="ck_...", base_url="https://gtm.cognethics.com") as c:
        # Generated tree
        invoices = await c.entity_crud.finance.invoice.list(page_size=10)

        # Ergonomic facade
        overdue = await c.invoices.list(status="overdue")

        # Developer Sandbox namespace
        await c.dev.ping()

        # Async pagination
        async for row in c.paginate(c.entity_crud.finance.invoice.list, page_size=50):
            print(row["id"])

asyncio.run(main())
```

Every generated method, facade, and `c.dev` call returns a coroutine under the async client — `await` them exactly as shown.

## Developer Sandbox (`client.dev`)

The `dev` namespace targets the unauthenticated/light-auth `/api/v1/dev/` surface and is the fastest way to verify a `ck_` key works:

```python
from cognethics import Client

client = Client(api_key="ck_...", base_url="https://gtm.cognethics.com")

# 1. Liveness probe — no auth required
client.dev.ping()
# → {"service": "cognethics-dev-api", "version": "v1", "status": "ok"}

# 2. Verify your key + identity context
client.dev.me()
# → {"authenticated": True, "key": {...}, "user": {...}, "tenant": {...}}

# 3. Echo arbitrary query params (debug helper)
client.dev.echo("hello", foo="bar")
```

`client.dev` errors raise the same exception classes used elsewhere in the SDK (`AuthenticationError`, `PermissionDenied`, `NotFound`, etc.), plus a catch-all `DevApiError` for unmapped 4xx codes.

## Calling low-level handlers

Every MCP handler exposed by the Cognethics platform is reachable in two ways:

```python
# 1. Generic dispatch — call any handler by name, including custom tools.
result = client.call(
    "prism_entity_crud",
    app="spare_parts",
    entity="work_order",
    operation="list",
)

# 2. Generated tree — type-friendly attribute access for entity_crud handlers.
result = client.entity_crud.spare_parts.work_order.list(page_size=10)
```

The generated tree is produced from the platform's introspection schema, so new entities show up automatically when the SDK is regenerated.

## Pagination

Use the `paginate` helper to iterate through multi-page results without managing cursors yourself:

```python
for row in client.paginate(client.entity_crud.finance.invoice.list, page_size=50):
    print(row["id"], row["amount"])
```

## Error handling

The SDK raises typed exceptions that map to the platform's standard error envelope:

```python
import cognethics

try:
    # Generated update methods take a `data` dict for the update payload.
    client.entity_crud.finance.invoice.update(
        id="<invoice-uuid>",
        data={"status": "paid"},
    )
except cognethics.PermissionDenied:
    print("This API key cannot update invoices in this org.")
except cognethics.NotFound:
    print("Invoice does not exist.")
except cognethics.ValidationError as exc:
    print(f"Invalid payload: {exc}")
```

## Org switching

The Cognethics platform is multi-tenant and multi-org. The active org depends on the auth method:

- **API-key auth**: each API key is bound to one organization at creation time. To work across organizations, mint a separate API key per org. The `org=` constructor argument and `_org=` per-call override are sent as `X-Organization-Context`.
- **OAuth bearer tokens**: the `org=` constructor argument and `_org=` per-call override switch the active organization via `X-Organization-Context`. The selected org must be one of the token's available organizations; naming an org outside the grant returns a permission error.

```python
# One API key per org
constance_client = Client(api_key="ck_constance_key", base_url="https://gtm.cognethics.com")
acme_client = Client(api_key="ck_acme_key", base_url="https://gtm.cognethics.com")

# One OAuth session, switching org per call
client = Client(access_token="ey...", refresh_token="...", oauth_client_id="...",
                base_url="https://gtm.cognethics.com")
client.invoices.list(_org="<org-uuid-within-grant>")
```

## Timeout & retry configuration

Both `Client` and `AsyncClient` retry on `429`, `502`, `503`, and `504` with exponential backoff (base 0.5s, doubling). `Retry-After` headers are honored on `429`. Defaults:

| Setting       | Default | Constructor arg |
| ------------- | ------- | --------------- |
| Timeout       | 30s     | `timeout=...`   |
| Max retries   | 3       | `max_retries=...` |

When retries are exhausted on a `429`, the SDK raises `RateLimit` with the `retry_after` field populated:

```python
from cognethics import Client, RateLimit

client = Client(api_key="ck_...", timeout=60.0, max_retries=5)

try:
    client.dev.me()
except RateLimit as exc:
    print(f"throttled — retry after {exc.retry_after}s")
```

## Design notes

- **Raw dicts by design**: the SDK uses plain dicts for request and response bodies. Pydantic models are intentionally kept out of the dependency footprint — agents typically read JSON-shaped data directly.
- **Generated from introspection**: the typed tree is produced from the platform's live introspection schema, so new entities and operations appear automatically when the SDK is regenerated.

## Documentation

- **For agents**: <https://developers.cognethics.com/for-agents/>
- **Full reference**: <https://developers.cognethics.com/reference/>
- **Recipes & guides**: <https://developers.cognethics.com/>
- **TypeScript SDK**: [`@cognethics/sdk`](https://www.npmjs.com/package/@cognethics/sdk) on npm — the same typed handler tree for TypeScript and JavaScript projects.
