# client.conversations

> client.conversations — the conversations operations.

`client.conversations` — the `conversations` operations.

On `AsyncKindgi` every method is the same, awaited.

## `client.conversations.list()`

```python signature
list(
    *,
    limit: int | None = None,
    cursor: str | None = None,
    scope_kind: Literal['tenant', 'org', 'project'] | None = None,
    scope_id: str | UUID | None = None,
    agent_id: str | UUID | None = None,
    status: Literal['open', 'closed'] | None = None,
    replays: Literal['exclude', 'include', 'only'] | None = None,
    timeout: float | None = None,
) -> ConversationCollectionPage
```

List conversations. `GET /v1/conversations`

Cursor-paginated. Fixed sort: `openedAt desc, id desc`. Filters: `?agentId=`, `?status=open|closed`, `?replays=exclude|include|only` (default `exclude`: a comparison's replay conversations are left out), and `scopeKind`/`scopeId` for one project's conversations, or every project's in an org. Conversations from before Kindgi 0.1.3 have no project and are listed only without a scope.

## `client.conversations.open()`

```python signature
open(
    body: OpenConversationBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> Conversation
```

Open a conversation. `POST /v1/conversations`

Pins `(agentId, agentVersion)` at open time. `title` defaults to `"Untitled conversation"` when omitted; `projectId` puts it in a project, which must reach the agent (lists filter by it; omitted, the agent's own project, as for a run, or the Default project for an agent filed under none); `scope` accepts arbitrary JSON.

## `client.conversations.get()`

```python signature
get(conversation_id: str | UUID, /, *, timeout: float | None = None) -> Conversation
```

Fetch a conversation. `GET /v1/conversations/{conversationId}`

## `client.conversations.close()`

```python signature
close(
    conversation_id: str | UUID,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
) -> Conversation
```

Close a conversation. `POST /v1/conversations/{conversationId}/close`

Idempotent: closing an already-closed conversation returns 200 with the current row (no timestamp bump).

## `client.conversations.unregister()`

```python signature
unregister(
    conversation_id: str | UUID,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
) -> Conversation
```

Unregister a conversation. `POST /v1/conversations/{conversationId}/unregister`

A tombstone: from now on no read, list or recall of earlier conversations returns it, and no message can be added. The retention sweep removes it after the tenant's grace.

## `client.conversations.messages()`

```python signature
messages(
    conversation_id: str | UUID,
    /,
    *,
    limit: int | None = None,
    cursor: str | None = None,
    timeout: float | None = None,
) -> ConversationMessageCollectionPage
```

Read conversation messages. `GET /v1/conversations/{conversationId}/messages`

Cursor-paginated. Sort is `sequence asc` (natural conversation reading order) — distinct from most list endpoints, which use `createdAt desc`.
