# Lookup endpoints

> How an app’s lookup endpoint gives an agent data from your own HTTP service, what Conclude sends, and what it does with the response.

Canonical HTML page: https://conclude.io/doc/apps/integrations/lookup/
Last updated: 2026-11-02

---

A lookup endpoint is an HTTPS URL that Conclude calls before an agent answers on a ticket. The agent can then read a record that your own system holds, such as a CRM entry. This page is for the builder who runs that service.

**YAML only.** The `lookup:` block has no editor form. Add it to the app YAML on the [Expert](https://conclude.io/doc/apps/editor/expert/) tab. It runs only when an [agent](https://conclude.io/doc/agents/) is attached to the app's trigger. Other triggers ignore it.

## Configure the lookup

```yaml
lookup:
  url: https://crm.example.com/conclude-enrich
  secret: crm_api_token
  on: [onCreate, onComment]
  timeout: 5s
```

- `url` must use `https`. Any other scheme is refused
- `secret` names an organization Secret, which Conclude sends as `Authorization: Bearer <token>`. An unknown name sends the request without the header. Secrets are encrypted records that belong to the organization. An organization administrator creates one through the internal organization API (`POST /fapi/organization/<organization>/secrets`), which authenticates with a cookie. The Dashboard has no page for them, and the per-app [secrets dialog](https://conclude.io/doc/admin/users-and-access/security/#secrets) (`/c app secrets`) is a different store
- `on` lists the events that fire the lookup. The events are `onCreate`, `onComment`, `onEdit` and `onConclude`. An empty list never fires
- `timeout` is a duration such as `10s`. The default is 5 seconds and the cap is 30 seconds. A value that Conclude cannot parse, or that is zero or negative, falls back to the default

Key types are in the [connectors reference](https://conclude.io/doc/reference/connectors/#lookup-endpoint).

## What Conclude sends

For each event listed in `on`, Conclude sends one `POST` to `url` with `Content-Type: application/json` and this body:

```json
{"event": "onCreate", "activity": {"title": "Login fails after upgrade", "email": "sam@example.com"}}
```

`activity.title` is the ticket title, and `activity.email` is the initiator's email address. Conclude omits either field when it is empty. It sends no other ticket data. It does not follow redirects, and a `3xx` answer counts as a failure.

## How the response is used

Only a `2xx` status counts. Conclude reads at most 4 KB of the body and trims the whitespace. It then inserts the text unchanged into the agent's system prompt, under a `## Customer context` heading. The text sits after the ticket state and before the trigger description. See [what the agent sees](https://conclude.io/doc/reference/agents/#what-the-agent-sees). Plain text and JSON both work. Conclude parses and filters nothing, so return only what the agent should read.

## Security and failures

- Conclude resolves the hostname when it validates the URL, and checks it again when the connection opens. DNS therefore cannot steer a lookup into an internal network. Conclude blocks loopback, private (RFC 1918 and IPv6 unique local), link-local, multicast, unspecified and carrier-grade NAT (`100.64.0.0/10`) addresses. It also blocks the IPv6 ranges `2001::/32` and `2002::/16`
- Conclude logs a timeout, a connection error, a blocked address or a non-`2xx` status. The agent then answers without lookup data
- The bearer token lives in the Secret, not in the app YAML, so sharing the YAML does not expose it

## Related pages

- [Agents](https://conclude.io/doc/agents/) explains how an agent is attached to an app
- [Agents reference](https://conclude.io/doc/reference/agents/#lookup-backed-context) covers the lookup in the agent handler
- [Triggers reference](https://conclude.io/doc/reference/triggers/#events) lists the events an app reacts to

