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

# Answers and profiles

> Ask a question and get words back with citations, or hand PoolKit a schema and get it filled with evidence for every field.

## Ask

```swift theme={null}
let answer = try await pool.context.ask("Which sneakers did I look at most this month?", using: grant)

if !answer.declined {
    print(answer.text)
    for id in answer.citations {
        let evidence = try await pool.context.evidence(id: id, using: grant)
    }
}
```

* PoolKit finds the context on the device: the best matches for the question, or what recurs when nothing matches.
* On iOS 26 with Apple Intelligence, Apple's on-device model writes the answer and nothing leaves the phone.
* When Apple's model is there but cannot run, cloud assist writes the answer, under the same permission.
* On other devices the answer is written by [cloud assist](https://docs.pool.day/cloud-assist.md), only when your configuration and the grant both allow it. Up to 40 things and excerpts are sent as text. Without that permission the call throws `PoolError.cloudAssistNotAllowed`.
* `answer.writtenBy` says which of the two wrote it. `answer.provenance` is always `inferred`.
* Citations are evidence identifiers from the device. An answer can only cite what it was given.
* `declined` is true when the model would not answer, for example a question about health. `text` is then empty.
* A question is 1 to 1,000 characters, counted as UTF-16 code units; `PoolContext.questionMaximumLength` holds the limit for your text field. An empty or longer question throws `PoolError.invalidRequest`.
* While Pool's service asks the SDK to wait, a cloud answer throws `PoolError.rateLimited` or `PoolError.serviceUnavailable` with the seconds left. Search, facets and recurring things keep answering on the device.

### Show the answer as it is written

`askUpdates` runs the same checks, retrieval and writers as `ask`, and hands over the text while a model writes it.

```swift theme={null}
var shown = ""
for try await update in pool.context.askUpdates("Which sneakers did I look at most this month?", using: grant) {
    switch update {
    case .searching:
        showSpinner()
    case .writing:
        shown = ""                      // a new writer starts over
    case .partial(let text):
        shown = text                    // the whole text so far, not just the newest words
    case .answer(let answer):
        shown = answer.declined ? "" : answer.text
    }
    render(shown)
}
```

* `.writing` after partial text means the first model could not finish and the next one starts over. Drop what you showed.
* The final `.answer` can be `declined` after partial text. Drop the partial text then too.
* On the device, Apple's model streams its words. With cloud assist, Pool's service sends them as Server-Sent Events: see [Service API](https://docs.pool.day/service.md#cloud-assist-answer-a-question).
* Cost and permission are the same as `ask`.

## Fill a profile

```swift theme={null}
let schema: JSONValue = [
    "type": "object",
    "properties": [
        "favouriteBrands": ["type": "array", "items": ["type": "string"]],
        "shoeSize": ["type": "string", "description": "EU shoe size, if a capture shows one"],
        "style": ["type": "string", "enum": ["sporty", "classic", "street"]],
    ],
]

let profile = try await pool.context.profile(schema: schema, using: grant)

profile.value                         // the object, with null where nothing was filled
profile.evidence["/favouriteBrands"]  // the evidence behind that field
profile.refused["/shoeSize"]          // .noEvidence, .sensitive or .invalid
```

* A profile always needs cloud assist, allowed by your configuration and by the grant. It sends up to 80 recurring things as text, never an image.
* Every field comes back with a value and its evidence, or with the reason it was left empty. Nothing is filled without evidence.
* Fields about health, religion, sexuality, ethnicity, politics, children, finances or credentials are always refused as `sensitive`.
* The schema is a JSON Schema subset: an `object` at the root; `type`, `properties`, `required`, `items`, `enum`, `description`, `title` and `additionalProperties: false`; at most 5 levels, 100 fields and 32 KB. Anything else throws `PoolError.invalidSchema` before a request is made.
* Fields are addressed by JSON Pointer, for example `/sizes/shoe`.

## What they cost

An answer written on the device is free. An answer written by cloud assist is 10 units and a profile is 25. See [pricing](https://pool.day/developers/pricing).


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