> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tai42.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Interaction outcomes (tai42_contract.interactions)

> The typed outcomes a resumed run returns: suspended, buffered, and failed.

The `ask` answer and interaction-state models.

`InteractionResponse` is the validated answer pushed onto the reply channel;
`InteractionState` is the mutable record the answer endpoint reads;
`SuspendedInteraction` is the sentinel an `async` ask returns in place of an answer.

## InteractionResponse

`tai42_contract.interactions.models.response.InteractionResponse`

```python theme={null}
class InteractionResponse(BaseModel)
```

The answer. Validated server-side before it wakes the caller.

`params` is the OPTIONAL opaque channel enrichment carried WITH the answer — the answer-path
counterpart of the bridge path's `params` and a
conversation entry's `params`: when a tap/reply that ANSWERS a pending ask also carries
channel-specific context (a tapped reply id, a template button payload, a referral, the
reply-to context the participant quoted) the channel encodes it as string entries here so the asking
flow reads them beside `answer`. The SAME transport vocabulary
(`validate_entry_params`) bounds it as every params seam;
the platform attaches no meaning and NO TRUST. `None` means no enrichment — a plain answer,
byte-identical to the pre-params envelope.

**Attributes**

| Attribute | Type |
| - | - |
| `interaction_id` | `str` |
| `answer` | `Any` |
| `answered_by` | `str` |
| `answered_at` | `datetime` |
| `params` | `dict[str, str] \| None` |

## InteractionState

`tai42_contract.interactions.models.response.InteractionState`

```python theme={null}
class InteractionState(BaseModel)
```

Mutable companion to the immutable stream entry, keyed by interaction id.

**Attributes**

| Attribute | Type |
| - | - |
| `status` | `Literal['pending', 'answered']` |
| `group_id` | `str` |
| `request` | `InteractionRequest` |
| `response` | `InteractionResponse \| None` |

## SuspendedInteraction

`tai42_contract.interactions.models.response.SuspendedInteraction`

```python theme={null}
class SuspendedInteraction(BaseModel)
```

The sentinel an `async` ask returns in place of an answer.

Any async-suspending tool returns it to signal the caller was parked, keyed by
`interaction_id` so the resume path can find the parked question. Generic:
a resuming driver's resume state is keyed by this id, not carried here.

**Attributes**

| Attribute | Type |
| - | - |
| `interaction_id` | `str` |
| `expiry_at` | `datetime \| None` |
| `resume_owner` | `str \| None` |
| `interaction_ids` | `list[str]` |
| `caller_interaction_ids` | `list[str]` |

## ResumeBuffered

`tai42_contract.interactions.models.response.ResumeBuffered`

```python theme={null}
class ResumeBuffered(BaseModel)
```

A resume that did NOT drive its super-step to a terminal: sibling asks are still open.

One super-step of a held run can park SEVERAL asks in parallel. Answering one of them
buffers that answer and leaves the step suspended until the last sibling resolves. A resuming
driver returns this in place of a terminal to say exactly that: `remaining_ids` are the
still-unanswered asks of the same step. It is NOT terminal — the platform's delivery chokepoint
delivers nothing for it (the run stays parked), and `visit` normalises it to the caller/user
partition of the remaining ids. Generic: it names interaction ids only, no driver
or engine state. Kept by TYPE through the run-tool seam alongside `SuspendedInteraction` so a
caller recognises a still-suspended step rather than mistaking it for a terminal result.

**Attributes**

| Attribute | Type |
| - | - |
| `remaining_ids` | `list[str]` |

## RunFailed

`tai42_contract.interactions.models.response.RunFailed`

```python theme={null}
class RunFailed(BaseModel)
```

A run's failed terminal returned across a chain fire; `outcome` is the failing driver's opaque mapping.

A driver that resumes another driver's run through a chain-delivery tool reads the failure by
TYPE, never by a status word inside the outcome: the outcome stays the failing driver's own
JSON mapping, carried whole. A continuation face raises
`RunTerminalFailed` with it, so the platform delivers FAILED.

**Attributes**

| Attribute | Type |
| - | - |
| `model_config` | — |
| `outcome` | `dict[str, Any]` |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.