---
title: "Send a prompt to the session's agent"
method: POST
path: "/api/v2/projects/{projectId}/sessions/{sessionId}/messages"
tags: ["Sessions"]
---

# Send a prompt to the session's agent

`POST /api/v2/projects/{projectId}/sessions/{sessionId}/messages`

## Request

- Base URL: `https://davinci-app.com`
- URL: `https://davinci-app.com/api/v2/projects/{projectId}/sessions/{sessionId}/messages`
- Auth: HTTP bearer

Gives the agent something to do. Starts a run if none is going, and adds a turn
to the conversation if one is.

This returns as soon as the agent has accepted the prompt, not when it has
finished — a run takes as long as the work takes. Follow it with `getSession`
and read `agent.status`, or let the SDK's `waitUntilDone` do that for you.

Acceptance is not the same as success. A `202` means the agent took the prompt;
a `409` means it refused, which happens when the run it belonged to has ended.
Recreate the session in that case rather than retrying the message.

The agent can change anything in the project and is charged for AI usage doing it, which
is why this needs the `agent:message` scope rather than a project write.

## Request body

- SendAgentMessageRequest
  - `message` string, required: What you want the agent to do.
  - `messageId` string: Your own id for this prompt, echoed back and recorded in the transcript. Generated for you if omitted.
  - `context` object: Opaque data kept with the session and returned to your webhook alongside the agent's replies. Davinci does not interpret it.
  - `model` string: A model key returned by `listAgentModels`. Omit it to use the calling account's default model. The choice applies to this prompt; every prompt that omits it uses the account default.
  - `modelOptions` object: Model configuration keyed by the option keys returned for the selected model by `listAgentModels`. Values may be strings, numbers, or booleans. Omitted options use that model's effective account defaults.
  - `webSearch` boolean: Whether the agent may use web search for this prompt.
  - `persona` string: The id of a persona the project defines, which sets who the agent is for this prompt and every one after it in the session. Omit to keep whichever persona the session is already running under; omitting it on the first prompt uses the project's default. This is an id, not a persona. An object is refused with `INVALID_PERSONA`, because a persona's name, purpose and approach are written into the system prompt — accepting one here would let a caller rewrite the instructions that decide what the agent will refuse to do. Define personas in the project, then name one. An id the project does not define is refused with `UNKNOWN_PERSONA` rather than quietly falling back to a default.

## Response `202`

The agent accepted the prompt. The run is now in progress.

- SendAgentMessageResponse
  - `sessionId` string, uuid, required
  - `taskId` string, required: The run the prompt joined.
  - `messageId` string, required
  - `status` string, required: Always `message_delivered` — a refusal is a `409`, not a status here.

## Other responses

- `400`: Invalid request. Error code is `MISSING_MESSAGE`, `MESSAGE_TOO_LARGE`, `INVALID_MESSAGE_ID`, `INVALID_CONTEXT`, `INVALID_PERSONA`, `UNKNOWN_PERSONA`, `INVALID_MODEL`, `UNKNOWN_MODEL`, `INVALID_MODEL_OPTIONS`, `INVALID_WEB_SEARCH`, `LLM_OPTION_UNKNOWN`, or `LLM_OPTION_VALUE_UNAVAILABLE`. `UNKNOWN_PERSONA` names a persona the project does not define, and carries `details.definedPersonas` — the ids that would have worked. The message is refused rather than run under a default persona you did not ask for. `UNKNOWN_MODEL` names a well-formed model key outside the calling account's effective profile and carries `details.availableModels`. An invalid model option identifies its model and option key in `details.model` and `details.option`.
- `401`: No credential was supplied, or the supplied credential is malformed, expired, or revoked. A credential that is present but unusable is never downgraded to an anonymous request.
- `403`: Authenticated but not authorized. Either the acting user lacks the required resource permission, the key's scope ceiling excludes it, or the endpoint rejects this credential type (`CREDENTIAL_NOT_PERMITTED`).
- `404`: No such session, it belongs to another user, or it belongs to a different project than the one in the path. Error code is `SESSION_NOT_FOUND`.
- `409`: The agent refused the message (`MESSAGE_REFUSED`), or the project the session opened is no longer running (`PROJECT_NOT_RUNNING`).
- `429`: Request rate exceeded, either globally or for this key.
- `500`: Unexpected server error.

## Changes

- **2026-09-15** (v2) `67c8b8616dbb`: 7 info
  - the `success` response property const value `false` was added for the status `400`
  - the `success` response property const value `false` was added for the status `401`
  - the `success` response property const value `false` was added for the status `403`
  - the `success` response property const value `false` was added for the status `404`
  - …3 more
- **2026-09-15** (v2) `48948af37797`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/celedon-solutions/apis/davinci-public-api/changes/api/v2/projects/:projectId/sessions/:sessionId/messages/post.md)

---

[API](https://skmtc.dev/celedon-solutions/apis/davinci-public-api.md) - [All operations](https://skmtc.dev/celedon-solutions/apis/davinci-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/celedon-solutions/apis/davinci-public-api/revisions/279218ca2e8d?raw)
