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

# Send an agent reply

> Send a message or side-effect into an existing agent conversation from your backend.

Use this endpoint when you are not using `@novu/framework` (for example Python, Go, PHP, .NET, or Java SDKs),
or when a server process outside the bridge needs to post into a live conversation.

**Message actions**
- `reply` — markdown, interactive card, or tool-approval card (optional `files`)
- `edit` — update a previously delivered message in place
- `deleteMessages` — remove rendered platform messages (history is kept)
- `addReactions` — add emoji reactions to existing messages

**Turn control**
- `typing` — `{ status?: string }` to set status, or `"stop"` to clear
- `resolve` — mark the conversation resolved (optionally with a final reply)
- `error: true` — report a customer-runtime failure (cannot combine with other actions)

**Signals & tools**
- `signals` — metadata set/delete/clear, or trigger a Novu workflow
- `toolResults` — persist tool outputs into conversation history
- `toolApprovalRequest` — ledger a gated tool call (pair with an approval card reply)

Returns `{ data: { messageId, platformThreadId } }` when a reply or edit is delivered;
otherwise `{ data: null }`.

Send a reply into an existing agent conversation from server-side code. Use this when you are not running `@novu/framework` on the bridge (for example with the Python, Go, PHP, .NET, or Java SDKs), or when another backend service needs to post into a live conversation.

The request body is a bag of optional actions. Provide at least one of `reply`, `edit`, `resolve`, `signals`, `toolResults`, `toolApprovalRequest`, `addReactions`, `deleteMessages`, `typing`, or `error`. Named examples in the OpenAPI spec cover the common shapes.

When a reply or edit is delivered, the response `data` contains `messageId` and `platformThreadId`. Side-effect-only requests return `data: null`.

For the TypeScript bridge API (`ctx.reply`, cards, signals), see [Reply](/agents/custom-code-agent/building-blocks/reply).


## OpenAPI

````yaml POST /v1/agents/{agentId}/reply
openapi: 3.0.0
info:
  title: Novu API
  description: >-
    Novu REST API. Please see https://docs.novu.co/api-reference for more
    details.
  version: 3.18.1
  contact:
    name: Novu Support
    url: https://discord.gg/novu
    email: support@novu.co
  termsOfService: https://novu.co/terms
  license:
    name: MIT
    url: https://opensource.org/license/mit
servers:
  - url: https://api.novu.co
  - url: https://eu.api.novu.co
security:
  - secretKey: []
tags:
  - name: Events
    description: >-
      Events represent a change in state of a subscriber. They are used to
      trigger workflows, and enable you to send notifications to subscribers
      based on their actions.
    externalDocs:
      url: https://docs.novu.co/workflows
  - name: Subscribers
    description: >-
      A subscriber in Novu represents someone who should receive a message. A
      subscriber's profile information contains important attributes about the
      subscriber that will be used in messages (name, email). The subscriber
      object can contain other key-value pairs that can be used to further
      personalize your messages.
    externalDocs:
      url: https://docs.novu.co/subscribers/subscribers
  - name: Topics
    description: >-
      Topics are a way to group subscribers together so that they can be
      notified of events at once. A topic is identified by a custom key. This
      can be helpful for things like sending out marketing emails or notifying
      users of new features. Topics can also be used to send notifications to
      the subscribers who have been grouped together based on their interests,
      location, activities and much more.
    externalDocs:
      url: https://docs.novu.co/subscribers/topics
  - name: Integrations
    description: >-
      With the help of the Integration Store, you can easily integrate your
      favorite delivery provider. During the runtime of the API, the
      Integrations Store is responsible for storing the configurations of all
      the providers.
    externalDocs:
      url: https://docs.novu.co/platform/integrations/overview
  - name: Workflows
    description: >-
      All notifications are sent via a workflow. Each workflow acts as a
      container for the logic and blueprint that are associated with a type of
      notification in your system.
    externalDocs:
      url: https://docs.novu.co/workflows
  - name: Messages
    description: >-
      A message in Novu represents a notification delivered to a recipient on a
      particular channel. Messages contain information about the request that
      triggered its delivery, a view of the data sent to the recipient, and a
      timeline of its lifecycle events. Learn more about messages.
    externalDocs:
      url: https://docs.novu.co/workflows/messages
  - name: Environments
    description: >-
      Environments allow you to manage different stages of your application
      development lifecycle. Each environment has its own set of API keys and
      configurations, enabling you to separate development, staging, and
      production workflows.
    externalDocs:
      url: https://docs.novu.co/platform/environments
  - name: Layouts
    description: Layouts are reusable wrappers for your email notifications.
    externalDocs:
      url: https://docs.novu.co/platform/workflow/layouts
  - name: Translations
    description: Used to localize your notifications to different languages.
    externalDocs:
      url: https://docs.novu.co/platform/workflow/advanced-features/translations
  - name: Domains
    description: Used to manage your inbound email domains.
    externalDocs:
      url: https://docs.novu.co/platform/domains
  - name: Agents
    description: >-
      Agents are conversational assistants that receive inbound messages from
      connected channels and respond through a custom code bridge or a managed
      runtime provider.
    externalDocs:
      url: https://docs.novu.co/agents
externalDocs:
  description: Novu Documentation
  url: https://docs.novu.co
paths:
  /v1/agents/{agentId}/reply:
    post:
      tags:
        - Agents
      summary: Send an agent reply
      description: >-
        Send a message or side-effect into an existing agent conversation from
        your backend.


        Use this endpoint when you are not using `@novu/framework` (for example
        Python, Go, PHP, .NET, or Java SDKs),

        or when a server process outside the bridge needs to post into a live
        conversation.


        **Message actions**

        - `reply` — markdown, interactive card, or tool-approval card (optional
        `files`)

        - `edit` — update a previously delivered message in place

        - `deleteMessages` — remove rendered platform messages (history is kept)

        - `addReactions` — add emoji reactions to existing messages


        **Turn control**

        - `typing` — `{ status?: string }` to set status, or `"stop"` to clear

        - `resolve` — mark the conversation resolved (optionally with a final
        reply)

        - `error: true` — report a customer-runtime failure (cannot combine with
        other actions)


        **Signals & tools**

        - `signals` — metadata set/delete/clear, or trigger a Novu workflow

        - `toolResults` — persist tool outputs into conversation history

        - `toolApprovalRequest` — ledger a gated tool call (pair with an
        approval card reply)


        Returns `{ data: { messageId, platformThreadId } }` when a reply or edit
        is delivered;

        otherwise `{ data: null }`.
      operationId: AgentReplyController_handleAgentReplyHandler
      parameters:
        - name: agentId
          required: true
          in: path
          description: Agent identifier (slug) for the agent that owns the conversation.
          example: support-agent
          schema:
            type: string
        - name: idempotency-key
          in: header
          description: A header for idempotency purposes
          required: false
          schema:
            type: string
      requestBody:
        required: true
        description: >-
          Reply payload. Provide at least one action: `reply`, `edit`,
          `resolve`, `signals`, `toolResults`, `toolApprovalRequest`,
          `addReactions`, `deleteMessages`, `typing`, or `error`. See named
          examples for common shapes used by server-side SDKs.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgentReplyPayloadDto'
            examples:
              markdownReply:
                summary: Markdown reply
                description: >-
                  Send a markdown (or plain text) message into an existing
                  conversation.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  reply:
                    markdown: '**Report ready.** Your weekly summary is attached.'
              replyWithFile:
                summary: Reply with file attachment
                description: >-
                  Attach files to a markdown reply. Provide exactly one of `url`
                  or `data` per file. Prefer `url` for larger files.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  reply:
                    markdown: Here is your report.
                    files:
                      - filename: report.pdf
                        mimeType: application/pdf
                        url: https://example.com/files/report.pdf
              cardReply:
                summary: Interactive card reply
                description: >-
                  Send a Chat SDK card (buttons, text, links). Build cards with
                  `@novu/framework` helpers or an equivalent JSON tree.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  reply:
                    card:
                      type: card
                      title: 'Order #123'
                      children:
                        - type: text
                          content: Your order is ready for pickup.
                        - type: button
                          id: confirm
                          label: Confirm
                          style: primary
              editMessage:
                summary: Edit a sent message
                description: >-
                  Update a previously delivered agent message in place. Cannot
                  be combined with resolve, signals, or reactions.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  edit:
                    messageId: '1712345678.123456'
                    content:
                      markdown: 'Updated: the report is now final.'
              typingStart:
                summary: Start typing indicator
                description: >-
                  Best-effort status text on platforms that support it. Omit
                  `status` for the default "Thinking…".
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  typing:
                    status: Looking up your order…
              typingStop:
                summary: Stop typing indicator
                description: Clear the typing / status indicator for this turn.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  typing: stop
              addReaction:
                summary: Add emoji reaction
                description: React to a platform message with a well-known emoji name.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  addReactions:
                    - messageId: '1712345678.123456'
                      emojiName: white_check_mark
              deleteMessage:
                summary: Delete a sent message
                description: >-
                  Remove a previously posted platform message. Conversation
                  history is preserved.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  deleteMessages:
                    - messageId: '1712345678.123456'
              resolveConversation:
                summary: Resolve conversation
                description: >-
                  Mark the conversation resolved. Optionally include a summary
                  and/or a final reply in the same request.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  reply:
                    markdown: Glad that helped — marking this as resolved.
                  resolve:
                    summary: Answered billing question about invoice INV-42.
              metadataSignal:
                summary: Set conversation metadata
                description: >-
                  Persist key/value metadata on the conversation for later
                  turns. Keys: 1–128 chars, letters/digits with `-`, `_`, `:`
                  separators.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  signals:
                    - type: metadata
                      action: set
                      key: crm:ticketId
                      value: TCK-1001
              triggerWorkflow:
                summary: Trigger a Novu workflow
                description: >-
                  Fire a workflow from the agent turn. When `to` is omitted,
                  Novu uses the conversation subscriber if one is resolved.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  signals:
                    - type: trigger
                      workflowId: order-shipped
                      to: subscriber-123
                      payload:
                        orderId: ORD-42
              toolResult:
                summary: Report tool results
                description: >-
                  Persist tool-call outcomes into conversation history
                  (typically before the assistant reply).
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  toolResults:
                    - toolCallId: call_abc123
                      toolName: lookup_order
                      output:
                        status: shipped
                        eta: '2026-07-16'
                      preview: Order ORD-42 is shipped
                  reply:
                    markdown: >-
                      Your order **ORD-42** has shipped and should arrive by
                      July 16.
              toolApprovalRequest:
                summary: Request tool approval
                description: >-
                  Ledger a gated tool call and optionally deliver an approval
                  card via `reply.toolApprovalCard` or a normal card/markdown
                  reply.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  toolApprovalRequest:
                    approvalId: apr_01HZX
                    toolCallId: call_refund_1
                    name: issue_refund
                    input:
                      orderId: ORD-42
                      amountCents: 2500
                  reply:
                    toolApprovalCard:
                      type: tool-approval-card
                      title: Approve refund?
                      subtitle: issue_refund · ORD-42 · $25.00
                      approveLabel: Approve
                      denyLabel: Deny
              turnError:
                summary: Report turn failure
                description: >-
                  Bridge reports that the customer runtime failed. Cannot be
                  combined with other actions. Novu delivers generic user-facing
                  copy.
                value:
                  conversationId: 64f5a1c2e8b7a3d9f0c1b2a3
                  integrationIdentifier: slack-support
                  error: true
      responses:
        '200':
          description: >-
            OK. When a reply or edit is delivered, `data` contains the platform
            message identifiers. Side-effect-only requests (typing, reactions,
            deletes, signals without an outbound message) return `data: null`.
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SentMessageInfoDto'
                nullable: true
        '400':
          description: Bad Request
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
        '401':
          description: Unauthorized
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
        '404':
          description: The agent or conversation was not found.
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
        '405':
          description: Method Not Allowed
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
        '409':
          description: Conflict
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
        '413':
          description: Payload Too Large
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
        '414':
          description: URI Too Long
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
        '415':
          description: Unsupported Media Type
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorDto'
        '429':
          description: 'The client has sent too many requests in a given amount of time. '
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
            Retry-After:
              $ref: '#/components/headers/Retry-After'
          content:
            application/json:
              schema:
                type: string
                example: API rate limit exceeded
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
        '503':
          description: >-
            The server is currently unable to handle the request due to a
            temporary overload or scheduled maintenance, which will likely be
            alleviated after some delay.
          headers:
            Content-Type:
              $ref: '#/components/headers/Content-Type'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            Idempotency-Key:
              $ref: '#/components/headers/Idempotency-Key'
            Idempotency-Replay:
              $ref: '#/components/headers/Idempotency-Replay'
            Retry-After:
              $ref: '#/components/headers/Retry-After'
          content:
            application/json:
              schema:
                type: string
                example: Please wait some time, then try again.
      security:
        - secretKey: []
      x-codeSamples:
        - lang: csharp
          label: Csharp (SDK)
          source: |-
            using Novu;
            using Novu.Models.Components;

            var sdk = new NovuSDK(secretKey: "YOUR_SECRET_KEY_HERE");

            var res = await sdk.Agents.SendReplyAsync(
                agentId: "support-agent",
                agentReplyPayloadDto: new AgentReplyPayloadDto() {
                    ConversationId = "64f5a1c2e8b7a3d9f0c1b2a3",
                    IntegrationIdentifier = "slack-support",
                    Reply = Reply.CreateMarkdownReplyContentDto(
                        new MarkdownReplyContentDto() {
                            Markdown = "**Report ready.** Your weekly summary is attached.",
                        }
                    ),
                }
            );

            // handle response
        - lang: php
          label: PHP
          source: |-
            declare(strict_types=1);

            require 'vendor/autoload.php';

            use novu;
            use novu\Models\Components;

            $sdk = novu\Novu::builder()
                ->setSecurity(
                    'YOUR_SECRET_KEY_HERE'
                )
                ->build();

            $agentReplyPayloadDto = new Components\AgentReplyPayloadDto(
                conversationId: '64f5a1c2e8b7a3d9f0c1b2a3',
                integrationIdentifier: 'slack-support',
                reply: new Components\MarkdownReplyContentDto(
                    markdown: '**Report ready.** Your weekly summary is attached.',
                ),
            );

            $response = $sdk->agents->sendReply(
                agentId: 'support-agent',
                agentReplyPayloadDto: $agentReplyPayloadDto

            );

            if ($response->object !== null) {
                // handle response
            }
        - lang: python
          label: Python
          source: |-
            import novu_py
            from novu_py import Novu


            with Novu(
                secret_key="YOUR_SECRET_KEY_HERE",
            ) as novu:

                res = novu.agents.send_reply(agent_id="support-agent", agent_reply_payload_dto=novu_py.AgentReplyPayloadDto(
                    conversation_id="64f5a1c2e8b7a3d9f0c1b2a3",
                    integration_identifier="slack-support",
                    reply=novu_py.MarkdownReplyContentDto(
                        markdown="**Report ready.** Your weekly summary is attached.",
                    ),
                ))

                # Handle response
                print(res)
        - lang: go
          label: Go
          source: "package main\n\nimport(\n\t\"context\"\n\t\"github.com/novuhq/novu-go/v3\"\n\t\"github.com/novuhq/novu-go/v3/models/components\"\n\t\"log\"\n)\n\nfunc main() {\n    ctx := context.Background()\n\n    s := v3.New(\n        v3.WithSecurity(\"YOUR_SECRET_KEY_HERE\"),\n    )\n\n    res, err := s.Agents.SendReply(ctx, \"support-agent\", components.AgentReplyPayloadDto{\n        ConversationID: \"64f5a1c2e8b7a3d9f0c1b2a3\",\n        IntegrationIdentifier: \"slack-support\",\n        Reply: v3.Pointer(components.CreateReplyMarkdownReplyContentDto(\n            components.MarkdownReplyContentDto{\n                Markdown: \"**Report ready.** Your weekly summary is attached.\",\n            },\n        )),\n    }, nil)\n    if err != nil {\n        log.Fatal(err)\n    }\n    if res.Object != nil {\n        // handle response\n    }\n}"
        - lang: typescript
          label: TypeScript
          source: |-
            import { Novu } from "@novu/api";

            const novu = new Novu({
              secretKey: "YOUR_SECRET_KEY_HERE",
            });

            async function run() {
              const result = await novu.agents.sendReply({
                conversationId: "64f5a1c2e8b7a3d9f0c1b2a3",
                integrationIdentifier: "slack-support",
                reply: {
                  markdown: "**Report ready.** Your weekly summary is attached.",
                },
              }, "support-agent");

              console.log(result);
            }

            run();
components:
  schemas:
    AgentReplyPayloadDto:
      type: object
      properties:
        conversationId:
          type: string
          description: >-
            Conversation id to reply into. Obtained from the inbound agent event
            / bridge payload.
          example: 64f5a1c2e8b7a3d9f0c1b2a3
        integrationIdentifier:
          type: string
          description: >-
            Channel integration identifier linked to the agent for this
            conversation (e.g. `slack-support`).
          example: slack-support
        reply:
          description: >-
            Outbound message content. Exactly one of `markdown`, `card`, or
            `toolApprovalCard`. Optional `files` attach to the message. Cannot
            be combined with `edit`.
          oneOf:
            - $ref: '#/components/schemas/MarkdownReplyContentDto'
            - $ref: '#/components/schemas/CardReplyContentDto'
            - $ref: '#/components/schemas/ToolApprovalCardReplyContentDto'
        toolApprovalRequest:
          description: >-
            Tool-lifecycle ledger row for a gated tool call. Pair with
            `reply.toolApprovalCard` (or another reply shape) to deliver the
            approval UI.
          allOf:
            - $ref: '#/components/schemas/ToolApprovalRequestPayloadDto'
        edit:
          description: >-
            In-place edit of a previously posted agent message. Cannot be
            combined with reply, resolve, signals, toolResults,
            toolApprovalRequest, addReactions, or deleteMessages.
          allOf:
            - $ref: '#/components/schemas/EditPayloadDto'
        resolve:
          description: >-
            Mark the conversation resolved. May be combined with a final
            `reply`.
          allOf:
            - $ref: '#/components/schemas/ResolveDto'
        signals:
          type: array
          description: >-
            Side-effect signals executed during this turn: conversation metadata
            mutations or Novu workflow triggers.
          items:
            oneOf:
              - $ref: '#/components/schemas/MetadataSetSignalDto'
              - $ref: '#/components/schemas/MetadataDeleteSignalDto'
              - $ref: '#/components/schemas/MetadataClearSignalDto'
              - $ref: '#/components/schemas/TriggerSignalDto'
        toolResults:
          description: >-
            Tool-call outcomes to persist in conversation history (typically
            before the assistant reply).
          type: array
          items:
            $ref: '#/components/schemas/ToolResultDto'
        addReactions:
          description: Emoji reactions to add to existing platform messages.
          type: array
          items:
            $ref: '#/components/schemas/AddReactionPayloadDto'
        deleteMessages:
          description: >-
            Delete previously posted platform messages. Removes the rendered
            message only — history is preserved.
          type: array
          items:
            $ref: '#/components/schemas/DeleteMessagePayloadDto'
        typing:
          description: >-
            Per-turn typing/status control. Pass `{ status?: string }` to
            set/update the status (omit `status` for "Thinking…"), or `"stop"`
            to clear it. Best-effort per platform.
          oneOf:
            - type: string
              enum:
                - stop
              description: Clear the typing indicator.
            - $ref: '#/components/schemas/TypingStatusDto'
          example:
            status: Looking up your order…
        error:
          type: boolean
          description: >-
            Bridge reports that the customer runtime failed this turn. Cannot be
            combined with other actions. Novu delivers generic user-facing error
            copy.
          example: true
      required:
        - conversationId
        - integrationIdentifier
    SentMessageInfoDto:
      type: object
      properties:
        messageId:
          type: string
          description: >-
            Platform-native message id of the delivered or edited message (e.g.
            Slack `ts`, Teams activity id).
          example: '1712345678.123456'
        platformThreadId:
          type: string
          description: >-
            Platform-native thread / conversation id where the message was
            delivered.
          example: C0123456789
      required:
        - messageId
        - platformThreadId
    ErrorDto:
      type: object
      properties:
        statusCode:
          type: number
          description: HTTP status code of the error response.
          example: 404
        timestamp:
          type: string
          description: Timestamp of when the error occurred.
          example: '2024-12-12T13:00:00Z'
        path:
          type: string
          description: The path where the error occurred.
          example: /api/v1/resource
        message:
          description: Value that failed validation
          oneOf:
            - type: string
              nullable: true
            - type: number
            - type: boolean
            - type: object
              nullable: true
            - type: array
              items:
                anyOf:
                  - type: string
                    nullable: true
                  - type: number
                  - type: boolean
                  - type: object
                    additionalProperties: true
          example: 'xx xx xx '
        ctx:
          type: object
          description: Optional context object for additional error details.
          additionalProperties: true
          example:
            workflowId: some_wf_id
            stepId: some_wf_id
        errorId:
          type: string
          description: >-
            Optional unique identifier for the error, useful for tracking using
            Sentry and 
                  New Relic, only available for 500.
          example: abc123
      required:
        - statusCode
        - timestamp
        - path
    ValidationErrorDto:
      type: object
      properties:
        statusCode:
          type: number
          description: HTTP status code of the error response.
          example: 404
        timestamp:
          type: string
          description: Timestamp of when the error occurred.
          example: '2024-12-12T13:00:00Z'
        path:
          type: string
          description: The path where the error occurred.
          example: /api/v1/resource
        message:
          description: Value that failed validation
          oneOf:
            - type: string
              nullable: true
            - type: number
            - type: boolean
            - type: object
              nullable: true
            - type: array
              items:
                anyOf:
                  - type: string
                    nullable: true
                  - type: number
                  - type: boolean
                  - type: object
                    additionalProperties: true
          example: 'xx xx xx '
        ctx:
          type: object
          description: Optional context object for additional error details.
          additionalProperties: true
          example:
            workflowId: some_wf_id
            stepId: some_wf_id
        errorId:
          type: string
          description: >-
            Optional unique identifier for the error, useful for tracking using
            Sentry and 
                  New Relic, only available for 500.
          example: abc123
        errors:
          type: object
          description: A record of validation errors keyed by field name
          additionalProperties:
            $ref: '#/components/schemas/ConstraintValidation'
          example:
            fieldName1:
              messages:
                - Field is required
                - Must be a valid email address
              value: invalidEmail
            fieldName2:
              messages:
                - Must be at least 18 years old
              value: 17
            fieldName3:
              messages:
                - Must be a boolean value
              value: true
            fieldName4:
              messages:
                - Must be a valid object
              value:
                key: value
            fieldName5:
              messages:
                - Field is missing
              value: null
            fieldName6:
              messages:
                - Undefined value
      required:
        - statusCode
        - timestamp
        - path
        - errors
    MarkdownReplyContentDto:
      type: object
      properties:
        markdown:
          type: string
          description: >-
            Plain text or markdown body. Converted to the platform-native format
            by Novu.
          example: '**Report ready.** Your weekly summary is attached.'
        files:
          description: >-
            Optional attachments (max 15). Each file needs exactly one of data
            or url.
          type: array
          items:
            $ref: '#/components/schemas/FileRefDto'
      required:
        - markdown
    CardReplyContentDto:
      type: object
      properties:
        card:
          type: object
          description: >-
            Interactive card as a Chat SDK element tree (`type: "card"`). Prefer
            building with `@novu/framework` Card helpers when using TypeScript.
          additionalProperties: true
          example:
            type: card
            title: 'Order #123'
            children:
              - type: text
                content: Your order is ready for pickup.
              - type: button
                id: confirm
                label: Confirm
                style: primary
        files:
          description: >-
            Optional attachments (max 15). Supported alongside cards on
            platforms that allow it (e.g. WhatsApp).
          type: array
          items:
            $ref: '#/components/schemas/FileRefDto'
      required:
        - card
    ToolApprovalCardReplyContentDto:
      type: object
      properties:
        toolApprovalCard:
          type: object
          description: >-
            Novu tool-approval card descriptor (`type: "tool-approval-card"`).
            Used with `toolApprovalRequest` to render Approve/Deny UI.
          additionalProperties: true
          example:
            type: tool-approval-card
            title: Approve refund?
            subtitle: issue_refund · ORD-42 · $25.00
            approveLabel: Approve
            denyLabel: Deny
        files:
          type: array
          items:
            $ref: '#/components/schemas/FileRefDto'
      required:
        - toolApprovalCard
    ToolApprovalRequestPayloadDto:
      type: object
      properties:
        approvalId:
          type: string
          description: Unique id for this approval request (matches the AI SDK approvalId).
          example: apr_01HZX
        toolCallId:
          type: string
          description: Id of the tool call awaiting approval.
          example: call_refund_1
        name:
          type: string
          description: Name of the gated tool.
          example: issue_refund
        input:
          type: object
          description: Tool input the model proposed.
          additionalProperties: true
          example:
            orderId: ORD-42
            amountCents: 2500
      required:
        - approvalId
        - toolCallId
        - name
    EditPayloadDto:
      type: object
      properties:
        messageId:
          type: string
          description: Platform message id of the message to edit.
          example: '1712345678.123456'
        content:
          description: >-
            Replacement content. Exactly one of markdown, card, or
            toolApprovalCard.
          oneOf:
            - $ref: '#/components/schemas/MarkdownReplyContentDto'
            - $ref: '#/components/schemas/CardReplyContentDto'
            - $ref: '#/components/schemas/ToolApprovalCardReplyContentDto'
      required:
        - messageId
        - content
    ResolveDto:
      type: object
      properties:
        summary:
          type: string
          description: >-
            Optional human-readable resolution summary stored on the
            conversation.
          example: Answered billing question about invoice INV-42.
    MetadataSetSignalDto:
      type: object
      properties:
        type:
          type: string
          enum:
            - metadata
        action:
          type: string
          enum:
            - set
          description: Defaults to `set` when omitted.
          default: set
        key:
          type: string
          description: >-
            Metadata key (1–128 chars; letters, digits, and `-` `_` `:`
            separators).
          example: crm:ticketId
        value:
          type: object
          description: JSON-serializable value to store.
          example: TCK-1001
      required:
        - type
        - key
        - value
    MetadataDeleteSignalDto:
      type: object
      properties:
        type:
          type: string
          enum:
            - metadata
        action:
          type: string
          enum:
            - delete
        key:
          type: string
          description: Metadata key to remove.
          example: crm:ticketId
      required:
        - type
        - action
        - key
    MetadataClearSignalDto:
      type: object
      properties:
        type:
          type: string
          enum:
            - metadata
        action:
          type: string
          enum:
            - clear
      required:
        - type
        - action
    TriggerSignalDto:
      type: object
      properties:
        type:
          type: string
          enum:
            - trigger
        workflowId:
          type: string
          description: Workflow identifier (same string used with `events.trigger`).
          example: order-shipped
        to:
          description: >-
            Recipient(s). Accepts a subscriberId string, subscriber object,
            topic object, or an array of those. When omitted, Novu falls back to
            the conversation subscriber.
          oneOf:
            - type: string
              example: subscriber-123
            - type: object
              additionalProperties: true
              example:
                subscriberId: subscriber-123
            - type: array
              items:
                oneOf:
                  - type: string
                  - type: object
                    additionalProperties: true
        payload:
          type: object
          description: Arbitrary payload forwarded to the workflow.
          additionalProperties: true
          example:
            orderId: ORD-42
      required:
        - type
        - workflowId
    ToolResultDto:
      type: object
      properties:
        toolCallId:
          type: string
          description: Id of the tool call this result resolves.
          example: call_abc123
        toolName:
          type: string
          description: Name of the tool that produced this result.
          example: lookup_order
        output:
          type: object
          description: JSON-serializable tool output (or the execution-denied marker).
        preview:
          type: string
          description: Human-readable preview for the display timeline.
          example: Order ORD-42 is shipped
      required:
        - toolCallId
    AddReactionPayloadDto:
      type: object
      properties:
        messageId:
          type: string
          description: Platform message id to react to.
          example: '1712345678.123456'
        emojiName:
          type: string
          description: >-
            Well-known cross-platform emoji name (e.g. `white_check_mark`,
            `thumbsup`).
          example: white_check_mark
      required:
        - messageId
        - emojiName
    DeleteMessagePayloadDto:
      type: object
      properties:
        messageId:
          type: string
          description: >-
            Platform message id to delete. Removes the rendered message only —
            history is preserved.
          example: '1712345678.123456'
      required:
        - messageId
    TypingStatusDto:
      type: object
      properties:
        status:
          type: string
          description: >-
            Status text shown while the agent works. Omit for the default
            "Thinking…".
          example: Looking up your order…
    ConstraintValidation:
      type: object
      properties:
        messages:
          type: array
          items:
            type: string
          description: List of validation error messages
          example:
            - Field is required
            - Invalid format
        value:
          description: Value that failed validation
          oneOf:
            - type: string
              nullable: true
            - type: number
            - type: boolean
            - type: object
            - type: array
              items:
                anyOf:
                  - type: string
                    nullable: true
                  - type: number
                  - type: boolean
                  - type: object
                    additionalProperties: true
          example: 'xx xx xx '
      required:
        - messages
    FileRefDto:
      type: object
      properties:
        filename:
          type: string
          description: Filename shown to the end user, including extension.
          example: report.pdf
        mimeType:
          type: string
          description: IANA MIME type of the file.
          example: application/pdf
        data:
          type: string
          description: >-
            Base64-encoded inline file bytes. Mutually exclusive with `url`.
            Decoded size must be ≤ 5 MB. Prefer `url` for larger files.
          example: JVBERi0xLjQK...
        url:
          type: string
          description: >-
            Publicly accessible HTTP(S) URL. Mutually exclusive with `data`.
            Server-side limits: 25 MB per file, 15 files per message, 50 MB
            aggregate.
          example: https://example.com/files/report.pdf
      required:
        - filename
  headers:
    Content-Type:
      required: true
      description: The MIME type of the response body.
      schema:
        type: string
      example: application/json
    RateLimit-Limit:
      required: false
      description: >-
        The number of requests that the client is permitted to make per second.
        The actual maximum may differ when burst is enabled.
      schema:
        type: string
      example: '100'
    RateLimit-Remaining:
      required: false
      description: The number of requests remaining until the next window.
      schema:
        type: string
      example: '93'
    RateLimit-Reset:
      required: false
      description: >-
        The remaining seconds until a request of the same cost will be
        refreshed.
      schema:
        type: string
      example: '8'
    RateLimit-Policy:
      required: false
      description: The rate limit policy that was used to evaluate the request.
      schema:
        type: string
      example: >-
        100;w=1;burst=110;comment="token
        bucket";category="trigger";cost="single"
    Idempotency-Key:
      required: false
      description: The idempotency key used to evaluate the request.
      schema:
        type: string
      example: '8'
    Idempotency-Replay:
      required: false
      description: Whether the request was a replay of a previous request.
      schema:
        type: string
      example: 'true'
    Retry-After:
      required: false
      description: >-
        The number of seconds after which the client may retry the request that
        was previously rejected.
      schema:
        type: string
      example: '8'
  securitySchemes:
    secretKey:
      type: apiKey
      name: Authorization
      in: header
      description: >-
        API key authentication. Allowed headers-- "Authorization: ApiKey
        <novu_secret_key>".
      x-speakeasy-example: YOUR_SECRET_KEY_HERE

````