> For the complete documentation index, see [llms.txt](https://docs.uptiq.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.uptiq.ai/platform-resources/skill-library/document-skills/document-fetch.md).

# Document Fetch

**Document Fetch** retrieves one or more documents previously uploaded in the same conversation or saved to persistent storage, and enforces strict access control while doing it. It works from the `documentId` that [Document Upload](/platform-resources/skill-library/document-skills/document-upload.md) returned.

It fetches in batches — you pass a list of document descriptors and get a result per document, so one bad ID doesn't sink the rest.

## How it works

1. **Input resolution** — uses `$input` (the previous skill's output) and `$secret` (vault secrets).
2. **Processing** — accepts an array of descriptors (`documentId`, `source`, `storagePath?`) and performs a batch fetch:
   * `documentId` + `source='conversation'` → fetches from the current conversation.
   * `documentId` + `source='storage'` → fetches from storage, at `storagePath` if given.
   * **Documents from other conversations are not accessible.**
3. **Execution** — blocking. All documents are retrieved within the one step.
4. **Response:**
   * **Success** — an array of results, each with content, metadata, source, and status.
   * **Partial** — some documents succeed and others fail (not found, unauthorized). The overall `statusCode` is `207`.
   * **Failure** — a missing or invalid `documents` array returns `400`.

## Worked example: retrieving customer agreements for review

A company manages customer onboarding through a workflow. Along the way, agreements — service contracts, privacy consents — are uploaded and saved to persistent storage. Later a customer calls with a question, and the agent needs their specific signed agreement to answer accurately.

**The problem.** The agreements are stored, but finding and opening the right one by hand is slow. The agent needs an automated way to retrieve a specific document in response to a customer query.

**The approach.** Give the agent a Document Fetch skill configured against persistent storage. Pass the `documentId` for the agreement — resolved from the customer record, or carried forward from an earlier step — and the skill returns a signed URL the agent can work from.

Because the skill accepts an array, one call can retrieve the contract, the consent, and the ID proof together, then branch on each result's own `statusCode`.

<figure><img src="/files/KCzwBBfMtma0cRBysydd" alt=""><figcaption><p>Configuring which documents to fetch, and their source</p></figcaption></figure>

<figure><img src="/files/m8xD7IzQ3j4gfKzlUQVT" alt="" width="563"><figcaption><p>Document Fetch data flow</p></figcaption></figure>

## Configuration reference

| Field         | Type   | Required | Description                                                            |
| ------------- | ------ | -------- | ---------------------------------------------------------------------- |
| `documents`   | array  | ✅        | Documents to fetch. Each item: `{ documentId, source, storagePath? }`. |
| `name`        | string | —        | Display label on the canvas.                                           |
| `description` | string | —        | Long-form help text.                                                   |

## Output

| Field        | Type           | Always | Description                                   |
| ------------ | -------------- | ------ | --------------------------------------------- |
| `results`    | array          | ✅      | One object per requested document.            |
| `statusCode` | number         | ✅      | Overall: `200` · `207` partial · `400`/`500`. |
| `error`      | string \| null | —      | Present if the overall execution failed.      |

**Each entry in `results`:**

| Field        | Type           | Description                                         |
| ------------ | -------------- | --------------------------------------------------- |
| `documentId` | string         | The ID that was requested.                          |
| `url`        | string \| null | Signed URL to download the document.                |
| `mimeType`   | string \| null | MIME type, e.g. `application/pdf`.                  |
| `fileName`   | string \| null | Original filename.                                  |
| `source`     | string         | `conversation` or `storage`.                        |
| `statusCode` | number         | Status **for this document** — `200`, `404`, `403`. |
| `error`      | string \| null | Error message for this document, if any.            |

{% hint style="info" %}
Check each result's own `statusCode`, not just the overall one. A `207` means the call worked but some documents didn't — the failures are only visible per item.
{% endhint %}

## Errors

| Condition                              | Status | Notes                                    |
| -------------------------------------- | ------ | ---------------------------------------- |
| Empty or missing `documents` array     | `400`  | Invalid input; the skill refuses to run. |
| Document not found                     | `404`  | Per item, inside `results`.              |
| Unauthorized cross-conversation access | `403`  | Isolation is enforced, not advisory.     |
| Internal error                         | `500`  | Unexpected exception.                    |

## Security

* **Cross-conversation access is strictly forbidden.** A document uploaded in one conversation cannot be fetched from another.
* `$secret` may be used for document ID lookup, not for content.
* Logs redact document content — only IDs, status codes, and error messages are recorded.
* All storage-based fetches are validated against `documentId`.

## Testing in isolation

* **Path** — `/skill-runtime/workflows/nodes/DocumentFetch/execute`
* **Method** — `POST`
* **Body:**

```json
{
  "nodeType": "DOCUMENT_FETCH",
  "config": { },
  "input": { }
}
```

***

To add this skill to an agent, see [Adding a Skill to the Agent](/agent-builder/build/adding-a-skill-to-the-agent.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.uptiq.ai/platform-resources/skill-library/document-skills/document-fetch.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
