> For the complete documentation index, see [llms.txt](https://docs.amigo.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.amigo.ai/developer-guide/platform-api/conversations/serve-agent-from-web-app.md).

# Serve an Agent From a Web App

This guide shows how to embed an Amigo Platform agent in your own web application without exposing workspace API keys or external integration secrets to the browser.

The production pattern is a backend-for-frontend (BFF):

1. Your backend stores an External Integration `client_id` and `client_secret`.
2. Your backend exchanges those credentials for a parent JWT with the `external_user_sessions:create` scope.
3. Your backend mints a short-lived external-user session JWT for the signed-in web user.
4. Your browser uses only that external-user JWT to call scoped conversation endpoints.
5. Your browser refreshes the external-user JWT through your backend when it is near expiry.

{% hint style="warning" %}
Never put the External Integration `client_secret`, parent access token, workspace API key, admin API key, or external-user refresh token in browser code. The browser should receive only the current external-user access token and non-secret session metadata.
{% endhint %}

## Prerequisites

Before you start, collect these values:

| Value                                                | Where it comes from                                            | Notes                                                                                                                                                                                                                           |
| ---------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AMIGO_PLATFORM_API_URL`                             | Amigo                                                          | Usually `https://api.platform.amigo.ai`. Token exchange is mounted at `/token`; workspace APIs are mounted under `/v1/{workspace_id}`.                                                                                          |
| `AMIGO_WORKSPACE_ID`                                 | Developer Console **Settings** page for the customer workspace | The workspace that owns the agent, service, integration, and user data. Make sure you are viewing the customer's workspace, not an internal or staging workspace, before copying the ID.                                        |
| `AMIGO_SERVICE_ID`                                   | Developer Console **Services** page                            | Open the service your web application will expose and copy its service ID. It should point at the desired agent and version set.                                                                                                |
| Admin or owner API key                               | Amigo dashboard or existing provisioning                       | Needed once to create the External Integration and credential. The caller must be able to create/update external integrations and create/delete API-key-backed credentials. Do not use this from browser code.                  |
| External Integration `client_id` and `client_secret` | Created below                                                  | Stored only in your backend secret manager.                                                                                                                                                                                     |
| Agent Forge Go `v0.1.3+`                             | Amigo Agent Forge Go CLI                                       | Required for `forge platform external-integration` and nested credential commands. Verify with `forge --version`.                                                                                                               |
| TypeScript SDK `@amigo-ai/platform-sdk` `v0.66.0+`   | npm package                                                    | Required for the External Integration, token exchange, external-user session, refresh, and conversation streaming helpers used below.                                                                                           |
| Customer subject key                                 | Your application                                               | A stable per-user key such as your internal user ID. Amigo stores only a keyed hash of this value.                                                                                                                              |
| `consumer_entity_id`                                 | Optional Amigo world model entity                              | Not required for authenticated or anonymous web conversations. Pass it only when the web user is already linked to a patient, member, customer, or other materialized entity that the agent should use as conversation context. |

You also need a customer backend that can authenticate the browser user before minting an authenticated Amigo token, or apply product-specific abuse controls before minting an anonymous Amigo token.

## Authenticated and Anonymous Conversations

External-user sessions support both authenticated customer accounts and anonymous guest sessions. Choose the subject type when your backend mints the external-user session:

| User mode                      | `subject_type` | `external_subject_key`                                                                                        | `consumer_entity_id`                                                                                                |
| ------------------------------ | -------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Authenticated customer account | `user`         | A stable internal user ID from your application. Do not use an email address or phone number that can change. | Optional. Pass it only if that app user is already linked to an Amigo world model entity.                           |
| Anonymous guest session        | `anonymous`    | A stable anonymous session or visitor key generated by your application.                                      | Usually omitted. Pass it only if your product intentionally links the guest session to a materialized Amigo entity. |

A pre-existing Amigo world model entity is not required to start agent conversations for authenticated customer accounts. When you omit `consumer_entity_id`, Amigo creates and uses a stable external subject derived from your `external_subject_key` and the conversation is still scoped to the selected `service_id`.

Pass `consumer_entity_id` when the agent needs to operate with an existing materialized entity, such as a patient, member, customer, lead, or account record. That lets the agent use the correct world model context and keeps the conversation associated with that entity. If the web user is not linked to a materialized entity yet, omit `consumer_entity_id` and create or link the entity later through your normal application flow.

Anonymous sessions use the same External Integration credential and conversation flow, but your backend remains responsible for abuse controls such as rate limits, CAPTCHA or bot checks, origin checks, and session expiration before minting or refreshing guest tokens. Do not expose External Integration credentials or Amigo refresh tokens to the browser for either mode.

## System Design

Use this boundary model:

| Component           | Responsibilities                                                                                                                                                                                               |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Customer browser    | Renders chat UI, holds the external-user access token in memory, creates conversations, sends user messages, and streams agent responses.                                                                      |
| Customer backend    | Authenticates the user, stores external integration secrets and external-user refresh tokens, exchanges parent credentials, mints and refreshes external-user tokens, applies your app's authorization checks. |
| Amigo Identity      | Issues parent JWTs, external-user JWTs, and rotating refresh tokens.                                                                                                                                           |
| Amigo Platform API  | Accepts the external-user JWT for scoped conversation access.                                                                                                                                                  |
| Amigo agent runtime | Runs the service's agent, context graph, tools, and safety behavior.                                                                                                                                           |

```mermaid
sequenceDiagram
    autonumber
    participant Browser as Customer browser
    participant Backend as Customer backend
    participant Identity as Amigo Identity /token
    participant Platform as Amigo Platform API
    participant Agent as Agent runtime

    Browser->>Backend: Request chat bootstrap with app session cookie
    Backend->>Backend: Verify user and resolve external_subject_key
    Backend->>Identity: grant_type=client_credentials<br/>client_id + client_secret<br/>scope=external_user_sessions:create
    Identity-->>Backend: Parent JWT, expires_in=900
    Backend->>Identity: grant_type=external_user_session<br/>Authorization: Bearer parent JWT<br/>workspace_id, service_id, subject_type,<br/>external_subject_key, optional consumer_entity_id,<br/>scope, ttl_seconds
    Identity-->>Backend: External-user JWT, refresh_token,<br/>session_id, consumer_subject_id, expires_in
    Backend->>Backend: Store refresh_token server-side
    Backend-->>Browser: External-user JWT, expires_in,<br/>service_id, optional entity_id
    Browser->>Platform: POST /v1/{workspace_id}/conversations<br/>Authorization: Bearer external-user JWT
    Platform->>Platform: Resolve service and create conversation record
    Platform-->>Browser: conversation_id
    Browser->>Platform: POST /conversations/{id}/turns<br/>Accept: text/event-stream<br/>Authorization: Bearer external-user JWT
    Platform->>Agent: Process turns
    Agent-->>Platform: Agent output
    Platform-->>Browser: SSE turn events
    Browser->>Backend: Refresh near expiry with app session cookie
    Backend->>Backend: Load server-side refresh_token
    Backend->>Identity: grant_type=refresh_token<br/>refresh_token + workspace_id
    Identity-->>Backend: New external-user JWT and new refresh_token
    Backend->>Backend: Replace stored refresh_token
    Backend-->>Browser: New external-user JWT and expires_in
```

## Create the External Integration

You can provision with `forge`, the TypeScript SDK, or direct HTTP. The examples below use Agent Forge Go `v0.1.3+` for one-time setup because it includes both `platform external-integration` and `platform external-integration credential` commands and prints the one-time secret clearly.

Check your Forge version:

```bash
forge --version
```

Configure Forge with a workspace-scoped admin or owner credential:

```bash
export PLATFORM_API_URL="https://api.platform.amigo.ai"
export PLATFORM_WORKSPACE_ID="<workspace-id>"
export PLATFORM_API_KEY="<admin-or-owner-platform-api-key>"
```

Create an integration record:

```bash
forge platform external-integration create \
  --body '{
    "name": "customer_web_app",
    "display_name": "Customer Web App",
    "description": "BFF integration for customer-hosted web chat"
  }' \
  --json
```

Save the returned `id` as `AMIGO_EXTERNAL_INTEGRATION_ID`.

Create a credential scoped to the service you will expose:

```bash
forge platform external-integration credential create "$AMIGO_EXTERNAL_INTEGRATION_ID" \
  --body '{
    "name": "web-chat-prod",
    "service_ids": ["<service-id>"]
  }' \
  --json
```

Save these response fields in your backend secret manager:

```env
AMIGO_PLATFORM_API_URL=https://api.platform.amigo.ai
AMIGO_WORKSPACE_ID=<workspace-id>
AMIGO_SERVICE_ID=<service-id>
AMIGO_EXTERNAL_INTEGRATION_CLIENT_ID=<client_id>
AMIGO_EXTERNAL_INTEGRATION_CLIENT_SECRET=<client_secret>
```

The `client_secret` is returned only on create and rotate. If you lose it, rotate the credential and store the replacement.

```bash
forge platform external-integration credential rotate \
  "$AMIGO_EXTERNAL_INTEGRATION_ID" "<credential-id>" \
  --json
```

## TypeScript SDK Snippets

The public SDK guide has a complete TypeScript walkthrough: [External User Text Conversations](https://github.com/amigo-ai/amigo-platform-typescript-sdk/blob/main/docs/guides/external-user-text-conversations.md). The snippets in this guide require `@amigo-ai/platform-sdk` `v0.66.0+`.

Install the SDK:

```bash
npm install @amigo-ai/platform-sdk
```

Create the integration credential from an admin or setup job:

```typescript
import { AmigoClient } from '@amigo-ai/platform-sdk'

const admin = new AmigoClient({
  apiKey: process.env.AMIGO_API_KEY!,
  workspaceId: process.env.AMIGO_WORKSPACE_ID!,
  baseUrl: process.env.AMIGO_PLATFORM_API_URL,
})

const integration = await admin.externalIntegrations.create({
  name: 'customer-portal',
  display_name: 'Customer Portal',
  description: 'Backend for customer text conversations',
})

const { credential, client_secret } = await admin.externalIntegrations.createCredential(
  integration.id,
  {
    name: 'production backend',
    service_ids: [process.env.AMIGO_SERVICE_ID!],
  },
)

console.log('client_id:', credential.client_id)
// Store client_secret immediately in your secrets manager.
```

Mint an external-user session from your backend:

```typescript
import { AmigoClient, EXTERNAL_USER_SESSION_CREATE_SCOPE } from '@amigo-ai/platform-sdk'

const backend = new AmigoClient({
  apiKey: process.env.AMIGO_API_KEY!,
  workspaceId: process.env.AMIGO_WORKSPACE_ID!,
  baseUrl: process.env.AMIGO_PLATFORM_API_URL,
})

const parent = await backend.tokens.exchangeClientCredentials({
  clientId: process.env.AMIGO_EXTERNAL_INTEGRATION_CLIENT_ID!,
  clientSecret: process.env.AMIGO_EXTERNAL_INTEGRATION_CLIENT_SECRET!,
  scope: EXTERNAL_USER_SESSION_CREATE_SCOPE,
})

const externalSession = await backend.tokens.createExternalUserSession({
  parentAccessToken: parent.access_token,
  externalSubjectKey: 'customer-user-123',
  subjectType: 'user',
  serviceId: process.env.AMIGO_SERVICE_ID!,
  consumerEntityId: process.env.AMIGO_CONSUMER_ENTITY_ID,
  ttlSeconds: 1800,
})
```

Use the child access token with a separate SDK client:

```typescript
const externalUser = new AmigoClient({
  apiKey: externalSession.access_token,
  workspaceId: process.env.AMIGO_WORKSPACE_ID!,
  baseUrl: process.env.AMIGO_PLATFORM_API_URL,
})

const conversation = await externalUser.conversations.create({
  service_id: process.env.AMIGO_SERVICE_ID!,
})

for await (const event of externalUser.conversations.streamTurn(conversation.id, {
  message: 'Can I get a Tuesday appointment?',
})) {
  if (event.event === 'token') process.stdout.write(event.text)
  if (event.event === 'done') break
}
```

## Runtime Backend Flow

Your backend exposes a route such as `POST /api/amigo/session`. It should:

1. Authenticate the web user with your normal app session.
2. Decide whether the user may access this Amigo service.
3. Choose `subject_type`:
   * `user` for authenticated customer accounts.
   * `anonymous` for guest sessions.
4. Set `external_subject_key` to a stable app-side key. Use a durable user ID, not an email address that can change.
5. Optionally set `consumer_entity_id` if the user is already linked to an Amigo world model entity.
6. Mint or reuse a cached parent token from `client_credentials`.
7. Mint an external-user session token, store the refresh token server-side, and return the access token metadata to the browser.

```typescript
import { AmigoClient, EXTERNAL_USER_SESSION_CREATE_SCOPE } from '@amigo-ai/platform-sdk'

const WORKSPACE_ID = process.env.AMIGO_WORKSPACE_ID!
const SERVICE_ID = process.env.AMIGO_SERVICE_ID!
const CLIENT_ID = process.env.AMIGO_EXTERNAL_INTEGRATION_CLIENT_ID!
const CLIENT_SECRET = process.env.AMIGO_EXTERNAL_INTEGRATION_CLIENT_SECRET!

const backend = new AmigoClient({
  apiKey: process.env.AMIGO_API_KEY!,
  workspaceId: WORKSPACE_ID,
  baseUrl: process.env.AMIGO_PLATFORM_API_URL,
})

type ParentToken = { accessToken: string; expiresAtMs: number }
let cachedParent: ParentToken | null = null

async function getParentAccessToken(): Promise<string> {
  const now = Date.now()
  if (cachedParent && cachedParent.expiresAtMs - now > 60_000) {
    return cachedParent.accessToken
  }

  const parent = await backend.tokens.exchangeClientCredentials({
    clientId: CLIENT_ID,
    clientSecret: CLIENT_SECRET,
    scope: EXTERNAL_USER_SESSION_CREATE_SCOPE,
  })

  cachedParent = {
    accessToken: parent.access_token,
    expiresAtMs: now + parent.expires_in * 1000,
  }
  return cachedParent.accessToken
}

export async function mintAmigoExternalUserSession(appUser: {
  id: string
  amigoEntityId?: string
}) {
  const parentAccessToken = await getParentAccessToken()

  const externalSession = await backend.tokens.createExternalUserSession({
    parentAccessToken,
    externalSubjectKey: appUser.id,
    subjectType: 'user',
    serviceId: SERVICE_ID,
    consumerEntityId: appUser.amigoEntityId,
    scope: 'conversations:create conversations:turn conversations:read_own conversations:close_own',
    ttlSeconds: 1800,
  })

  await persistExternalUserRefreshToken({
    appUserId: appUser.id,
    refreshToken: externalSession.refresh_token,
    sessionId: externalSession.session_id,
    accessTokenExpiresAt: Date.now() + externalSession.expires_in * 1000,
  })

  return {
    access_token: externalSession.access_token,
    token_type: externalSession.token_type,
    expires_in: externalSession.expires_in,
    scope: externalSession.scope,
    session_id: externalSession.session_id,
    consumer_subject_id: externalSession.consumer_subject_id,
    subject_type: externalSession.subject_type,
    consumer_entity_id: externalSession.consumer_entity_id,
    workspace_id: WORKSPACE_ID,
    service_id: SERVICE_ID,
  }
}
```

If you use `@amigo-ai/platform-sdk` `v0.66.0+` server-side, the equivalent token resource methods are `client.tokens.exchangeClientCredentials()`, `client.tokens.createExternalUserSession()`, and `client.tokens.refresh()`.

## Browser Conversation Flow

After your backend returns an external-user token, create a conversation and send turns with that token. For streaming UI, call the turn endpoint with `Accept: text/event-stream`.

```typescript
import { AmigoClient } from '@amigo-ai/platform-sdk'

const session = await getAmigoSessionFromYourBackend()

const externalUser = new AmigoClient({
  apiKey: session.access_token,
  workspaceId: session.workspace_id,
  baseUrl: 'https://api.platform.amigo.ai',
})

const conversation = await externalUser.conversations.create({
  service_id: session.service_id,
})

for await (const event of externalUser.conversations.streamTurn(conversation.id, {
  message: 'Hello',
})) {
  renderAmigoTurnEvent(event)
  if (event.event === 'done') break
}
```

When rendering streamed turns:

* Append user messages optimistically when the browser sends them.
* Render `token` events only as provisional text if you want a typing effect.
* Commit `message` events as the completed agent messages in the chat transcript.
* External-user streams never include `tool_call_started` / `tool_call_completed` events - tool-call detail is workspace-credential-only, and requesting `include_tool_calls=true` with an external-user token returns 403. During tool-backed turns, expect a quiet gap after `token`/`thinking` activity and keep the response UI pending until the final `message` and `done` events arrive.
* On page load, refresh, or reconnect, reload history with `GET /conversations/{id}` and render `turns[].role` / `turns[].text`.
* Do not use `/calls/{id}` or `agent_transcript` to render web chat history. Those fields are for call-oriented transcript views, not customer web chat.
* **Handle deferred tool results.** When a turn returns `background_pending: true`, the message you just rendered is only an acknowledgement - continuation work is still pending. If continuation processing succeeds, a later answer is appended to durable conversation state; completion time depends on the tool and its dependencies, and `background_pending` does not guarantee that a final answer will be produced. Keep the turn in a "working…" state and drain the result: send the next user turn, or poll with `POST /conversations/{id}/turns?poll=true` and an empty request body (no message) until the API reports no pending work or an explicit failure or terminal outcome. Combining `poll=true` with a non-empty message returns `422`; the SDK wrapper `pollTurn()` handles this for you. Do not treat the acknowledgement as final, and do not subscribe the browser to `/events/stream` for this - that is a workspace-wide observer bus, not the per-chat delivery path. See [Background (deferred) tool results](/developer-guide/platform-api/conversations.md#background-deferred-tool-results).

For a production UI:

* Keep the external-user `access_token` in memory when possible.
* Refresh before `expires_in` elapses, with a buffer such as 60 seconds.
* Refresh by calling your backend with the user's normal app session cookie; do not pass a refresh token from the browser.
* Use the latest access token for every conversation request.
* If refresh fails with `invalid_grant`, discard the current access token, clear the server-side refresh token, and mint a new external-user session after revalidating the app user.

{% hint style="info" %}
The `sessions/connect` WebSocket endpoint is for materialized world-model entities and requires an `entity_id` query parameter. For External Integration web chat, prefer the Conversations REST/SSE endpoints shown above because they derive the correct entity binding from the external-user JWT and enforce the token's `service_id` and external-user scopes.
{% endhint %}

## Refresh Endpoint in Your Backend

Expose a backend route such as `POST /api/amigo/session/refresh`. It should verify the app session, load the current server-side refresh token for that app user/session, and call Amigo's refresh grant with `workspace_id`.

```typescript
export async function refreshAmigoExternalUserSession(appUser: { id: string }) {
  const tokenState = await loadExternalUserRefreshToken({ appUserId: appUser.id })
  if (!tokenState?.refreshToken) {
    throw new Error('No active Amigo external-user session')
  }

  const refreshed = await backend.tokens.refresh({
    refreshToken: tokenState.refreshToken,
    workspaceId: WORKSPACE_ID,
  })

  await persistExternalUserRefreshToken({
    appUserId: appUser.id,
    refreshToken: refreshed.refresh_token,
    sessionId: refreshed.session_id,
    accessTokenExpiresAt: Date.now() + refreshed.expires_in * 1000,
  })

  return {
    access_token: refreshed.access_token,
    token_type: refreshed.token_type,
    expires_in: refreshed.expires_in,
    scope: refreshed.scope,
    session_id: refreshed.session_id,
    consumer_subject_id: refreshed.consumer_subject_id,
    subject_type: refreshed.subject_type,
    consumer_entity_id: refreshed.consumer_entity_id,
    workspace_id: WORKSPACE_ID,
    service_id: SERVICE_ID,
  }
}
```

Return the new access token to the browser and replace the stored refresh token after every successful refresh.

## JWT, TTL, and Refresh Lifecycle

There are two JWT levels in this flow.

| Token                       | Holder                | How it is minted                                                                          | TTL                                                                                                  | Purpose                                                               |
| --------------------------- | --------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| Parent JWT                  | Customer backend only | `grant_type=client_credentials` with External Integration `client_id` and `client_secret` | `expires_in=900` seconds                                                                             | Delegation token that can mint external-user sessions only.           |
| External-user JWT           | Browser               | `grant_type=external_user_session` using the parent JWT                                   | Default `3600` seconds. `ttl_seconds` may be `900` to `3600`.                                        | Runtime token for the signed-in or anonymous web subject.             |
| External-user refresh token | Customer backend only | Returned with the external-user JWT                                                       | Absolute session limit is 7 days; idle timeout is the external-user token TTL selected at mint time. | Rotates the browser session without re-exchanging parent credentials. |

External-user JWT claims include:

| Claim                 | Meaning                                                             |
| --------------------- | ------------------------------------------------------------------- |
| `principal_type`      | Always `external_user`.                                             |
| `sub`                 | The Amigo `consumer_subject_id`.                                    |
| `workspace_id`        | Workspace the token is bound to.                                    |
| `credential_id`       | Parent External Integration credential ID.                          |
| `session_id`          | External-user session ID.                                           |
| `consumer_subject_id` | Stable Amigo subject created from your `external_subject_key` hash. |
| `subject_type`        | `user` or `anonymous`.                                              |
| `consumer_entity_id`  | Present only when you pass a materialized Amigo entity.             |
| `service_id`          | The only service this token can use.                                |
| `scopes`              | Subset of external-user scopes granted for this session.            |

External-user scopes are restricted to:

* `conversations:create`
* `conversations:turn`
* `conversations:read_own`
* `conversations:close_own`
* `conversations:approve_own` - enables the subject of care to approve or reject a parked, approval-gated write in their own conversation (the self-approval path)

A mint request with no explicit `scope` parameter grants all five.

Refresh lifecycle details:

* The parent JWT is not refreshed. When it expires, your backend repeats the `client_credentials` exchange.
* The browser must send refresh requests through your backend using its normal app authentication; it should not hold the Amigo refresh token.
* The refresh grant must include `workspace_id` for external-user refresh tokens.
* Each successful refresh returns a new access token and a new refresh token.
* The previous refresh token is rotated away. Replace the server-side stored token immediately.
* A short 30-second grace window makes retrying the same refresh request idempotent if the client loses the response.
* Reusing an old refresh token after the grace window is treated as token reuse and revokes the token family.
* Refresh fails if the External Integration credential is revoked, expired, inactive, or no longer allows the session's `service_id`.
* Refresh fails if the external-user session is revoked, the workspace is inactive, the session has been idle longer than its selected TTL, or the 7-day absolute session lifetime has elapsed.

## Operational Guidance

* Use one External Integration credential per deployed web application and environment.
* Scope each credential to the smallest service allowlist possible.
* Rotate External Integration credentials on a schedule and immediately after suspected exposure.
* Cache the parent JWT server-side only until `expires_in` minus a safety buffer.
* Handle `429` responses and honor `Retry-After` on token and conversation calls.
* Log token mint and refresh failures by status and error code, but never log token values.
* Treat `external_subject_key` as stable identity material. Use an internal immutable ID rather than email or phone number.
* For linked users, prefer passing `consumer_entity_id` so the agent can use the correct world model context.
* For guest users, use `subject_type=anonymous` and a stable anonymous session key.

## Related References

* [External Integrations](/developer-guide/platform-api/integrations/external-integrations.md)
* [External User Subject-Key Binding](/developer-guide/platform-api/integrations/external-user-subject-key-binding.md)
* [Sessions](/developer-guide/platform-api/platform-api/sessions.md)
* [Conversations](/developer-guide/platform-api/conversations.md)
* [Platform SDK Configuration](/developer-guide/platform-api/platform-sdk/configuration.md)
* [Public SDK guide: External User Text Conversations](https://github.com/amigo-ai/amigo-platform-typescript-sdk/blob/main/docs/guides/external-user-text-conversations.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.amigo.ai/developer-guide/platform-api/conversations/serve-agent-from-web-app.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.
