Metadata-Version: 2.4
Name: askconfer
Version: 0.9.0
Summary: Python SDK for Confer — distributed-knowledge inquiries, humans and agents on the same surface.
Author: Confer
License: MIT
Project-URL: Homepage, https://confer.team
Project-URL: Documentation, https://confer.team/documentation
Project-URL: Source, https://github.com/diligencemachines/confer
Keywords: mcp,confer,askconfer,agents,human-in-the-loop,llm,inquiries
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.25.0

# askconfer

Python SDK for Confer. Mirrors [`@askconfer/sdk`](https://www.npmjs.com/package/@askconfer/sdk).

## Install

```bash
pip install askconfer
```

The import name is `confer_sdk` (unchanged):

```python
from confer_sdk import Confer
```

## Use

```python
from confer_sdk import Confer

confer = Confer(
    api_url="https://your-deployment.vercel.app/api/mcp",
    api_token="confer_...",
)

# Open an inquiry against a group, with a webhook on terminal state.
created = confer.inquiries.create(
    recipe_id="brainstorm",
    group_id="5b8...",
    input={
        "topic": "Q2 launch risks",
        "context": "Onboarding flow ships in April.",
    },
    external_id="tenant_acme_42",
    notify_url="https://your-app.example.com/webhooks/confer",
    notify_secret="<your-shared-secret>",
)

# Or — short-running, want the answer inline:
result = confer.inquiries.create(
    recipe_id="brainstorm",
    group_id="5b8...",
    input={"topic": "Q2 launch risks"},
    external_id="tenant_acme_42",
    block_ms=90_000,  # long-poll up to 90s (the cap); omit or pass 0 for an explicit-async open handle
)

print(result.get("output"))
```

`external_id` is optional on every create surface. When supplied, use
any opaque tenant/user/project id and every `*.list` call will accept
it as a partition filter; when omitted the row is created in the
caller's org without a tenant tag (the org boundary still applies).

## Async

```python
from confer_sdk.aio import AsyncConfer

async with AsyncConfer(api_url=..., api_token=...) as confer:
    result = await confer.inquiries.create(
        recipe_id="retrospective",
        group_id="5b8...",
        input={"period_label": "Sprint 24"},
        external_id="tenant_acme_42",
    )
```

The async surface mirrors the sync one method-for-method.

## Surface

- `confer.recipes.{list, get, list_for_group}`
- `confer.groups.{list, get, create, update, delete, add_member,
  add_members, set_members, remove_member, add_agent, remove_agent,
  enable_recipe, disable_recipe, list_enabled_recipes}`
- `confer.agents.{list, get, create, update, delete, clone_to_group}`
- `confer.agent_types.{list, get}` — closed catalog of agent archetypes
- `confer.context_primitives.{list, get}` — primitive JSON Schemas
- `confer.agent_knowledge_facts.{list, add, update, remove,
  upload_document}`
- `confer.inquiries.{create, get, get_responders, list, cancel, extend_deadline}`
- `confer.sandbox_runs.{create, list}` — preview-then-launch sandbox flow
- `confer.members.update(member_id=..., name=..., email=...)`
- `confer.ask_human(respondent=..., recipe_id=..., input=..., **kwargs)` —
  single-respondent ask; same recipe library + magic-link delivery as
  `inquiries.create` but no group synthesis. Supports the same `block_ms`
  long-poll knob (capped at 30 min for `ask_human`).
- `confer.refer_human(topic=..., limit=..., include_paused=...)` — lookup-only
  ranked list of workspace humans for `topic`. Does **not** open an inquiry;
  pair with `ask_human`.

> Member-key asymmetry: `groups.add_member(group_id=..., email=...)`
> keys on `email` (the member id doesn't exist on first add), but
> `groups.remove_member(group_id=..., member_id=...)` keys on
> `member_id` (once the member exists, the id is the stable handle —
> fetch it from `groups.get(...).members`). Intentional; surfaced here
> so it's not a surprise when you wire the two calls.
- `confer.inquiries.create(..., block_ms=N)` — create + long-poll up
  to N ms inline; `block_ms` is hard-capped at 90,000 ms / 90s. Omit
  `block_ms` (or pass `0` as an explicit-async alias) to return
  immediately with an open handle. `expires_in_seconds` sets the
  inquiry's lifetime (a different knob). Replaces the former
  `confer.ask()`.

See [CHANGELOG.md](./CHANGELOG.md) for release history.

## Errors

All calls raise `ConferError(code, message, data)` on failure. Common
codes: `unauthorized`, `rate_limited`, `tool_error`, `network`,
`http_error`, `jsonrpc_*`.

## License

MIT.
