bothy-sdk
    Preparing search index...

    Class Outbox

    Sends replies and writes in order per thread and never twice.

    const outbox = new Outbox(api, { store: new FileOutboxStore("/var/lib/lotse/outbox.json") });
    await outbox.flush();
    const entry = await outbox.sendMessage(threadId, "Done", { runId });
    entry.state; // "sent", "pending" (resent by the next flush) or "failed"
    Index

    Constructors

    Properties

    Methods

    Constructors

    Properties

    The REST client.

    The storage.

    Methods

    • Stores a write with a new Idempotency-Key and sends it.

      The write is stored as method, path, parameters and body, so a later process sends the same request with the same key from Outbox.flush.

      Type Parameters

      • M extends OutboxMethod
      • P extends
            | "/interactions/{interaction_id}/respond"
            | "/instance/discovery"
            | "/instance/jwks"
            | "/instance/webhook-keys"
            | "/instance/branding/logo"
            | "/problems/{code}"
            | "/auth/oidc/begin"
            | "/auth/oidc/callback"
            | "/auth/oidc/complete"
            | "/auth/trusted-header/login"
            | "/auth/passkey/begin"
            | "/auth/passkey/complete"
            | "/auth/enroll/begin"
            | "/auth/enroll/complete"
            | "/auth/enroll/redeem"
            | "/auth/pairing/begin"
            | "/auth/pairing/complete"
            | "/auth/password/login"
            | "/auth/token/refresh"
            | "/auth/logout"
            | "/auth/step-up/challenge"
            | "/auth/step-up/passkey"
            | "/auth/step-up/device-key"
            | "/auth/step-up/password"
            | "/auth/step-up/oidc"
            | "/auth/step-up/oidc/complete"
            | "/console/session"
            | "/console/session/view-as"
            | "/csp-reports"
            | "/me"
            | "/me/profile"
            | "/me/avatar"
            | "/me/credentials"
            | "/me/identities/begin"
            | "/me/identities/complete"
            | "/me/passkeys/begin"
            | "/me/passkeys/complete"
            | "/me/local-credential"
            | "/me/mentions"
            | "/me/templates"
            | "/users"
            | "/users/{user_id}"
            | "/users/{user_id}/disable"
            | "/users/{user_id}/enable"
            | "/users/{user_id}/enrollment-codes"
            | "/users/{user_id}/credentials"
            | "/users/{user_id}/identities/{identity_id}"
            | "/users/{user_id}/passkeys/{passkey_id}"
            | "/users/{user_id}/devices"
            | "/users/{user_id}/sessions"
            | "/users/{user_id}/view-as"
            | "/owners"
            | "/owners/{user_id}/revoke"
            | "/me/devices"
            | "/me/devices/pairings"
            | "/devices/{device_id}"
            | "/devices/{device_id}/approve"
            | "/devices/{device_id}/revoke"
            | "/me/devices/current/push-registrations"
            | "/push-registrations/{registration_id}"
            | "/push/preview"
            | "/me/sessions"
            | "/me/sessions/extensions"
            | "/sessions/{session_id}/revoke"
            | "/principals/{principal_id}/tokens"
            | "/tokens/{token_id}"
            | "/groups"
            | "/groups/{group_id}"
            | "/groups/{group_id}/members"
            | "/groups/{group_id}/members/{user_id}"
            | "/grants"
            | "/grants/preview"
            | "/grants/{grant_id}"
            | "/grants/{grant_id}/revoke"
            | "/spaces/{space_id}/access"
            | "/channels/{channel_id}/access"
            | "/access/hints"
            | "/access/expiring"
            | "/instance"
            | "/instance/settings"
            | "/instance/settings/{key}"
            | "/instance/branding"
            | "/instance/agent-billing-mode"
            | "/feature-flags"
            | "/feature-flags/{key}"
            | "/signing-keys/rotate"
            | "/identity-providers"
            | "/identity-providers/{provider_id}"
            | "/spaces"
            | "/spaces/{space_id}"
            | "/spaces/{space_id}/move"
            | "/spaces/{space_id}/archive"
            | "/spaces/{space_id}/operator"
            | "/me/sidebar"
            | "/me/sidebar/spaces/{space_id}"
            | "/spaces/{space_id}/channels"
            | "/channels/{channel_id}"
            | "/channels/{channel_id}/move"
            | "/channels/{channel_id}/archive"
            | "/channels/{channel_id}/behavior"
            | "/channels/{channel_id}/operator"
            | "/channels/{channel_id}/read-only"
            | "/channels/{channel_id}/project-binding"
            | "/channels/{channel_id}/tags"
            | "/channels/{channel_id}/tags/{tag_id}"
            | "/channels/{channel_id}/tags/{tag_id}/move"
            | "/channels/{channel_id}/templates"
            | "/templates/{template_id}"
            | "/channels/{channel_id}/export"
            | "/me/dms"
            | "/dms"
            | "/channels/{channel_id}/leave"
            | "/channels/{channel_id}/incoming-webhooks"
            | "/incoming-webhooks/{webhook_id}"
            | "/hooks/{webhook_id}"
            | "/hooks/{webhook_id}/{token}"
            | "/channels/{channel_id}/threads"
            | "/threads/{thread_id}"
            | "/threads/{thread_id}/title"
            | "/threads/{thread_id}/close"
            | "/threads/{thread_id}/reopen"
            | "/threads/{thread_id}/move"
            | "/threads/{thread_id}/tags"
            | "/threads/{thread_id}/agent-sessions"
            | "/threads/{thread_id}/agent-sessions/reset"
            | "/threads/{thread_id}/agent-sessions/bind"
            | "/threads/{thread_id}/agent-sessions/report"
            | "/threads/{thread_id}/runs"
            | "/threads/{thread_id}/costs"
            | "/threads/{thread_id}/pins"
            | "/threads/{thread_id}/read-state"
            | "/threads/{thread_id}/read-state/mark-unread"
            | "/threads/{thread_id}/draft"
            | "/channels/{channel_id}/draft"
            | "/threads/{thread_id}/messages"
            | "/messages/{message_id}"
            | "/messages/{message_id}/revisions"
            | "/messages/{message_id}/reactions"
            | "/messages/{message_id}/reactions/{emoji}"
            | "/messages/{message_id}/pin"
            | "/components/{component_id}/interactions"
            | "/components/{component_id}"
            | "/channels/{channel_id}/uploads"
            | "/uploads/{file_id}/parts/{part_number}"
            | "/uploads/{file_id}/complete"
            | "/uploads/{file_id}"
            | "/files/{file_id}"
            | "/files/{file_id}/content"
            | "/files/{file_id}/thumbnails/{variant}"
            | "/files/{file_id}/tickets"
            | "/files/{file_id}/transcript"
            | "/files/{file_id}/transcribe"
            | "/search"
            | "/search/thread-titles"
            | "/sync/snapshot"
            | "/events"
            | "/me/read-states"
            | "/me/drafts"
            | "/me/settings"
            | "/me/settings/{key}"
            | "/me/notification-preferences"
            | "/me/notification-preferences/{target_kind}/{target_id}"
            | "/me/quiet-hours"
            | "/me/quiet-hours/{rule_id}"
            | "/client-metrics"
            | "/agents"
            | "/agents/{agent_id}"
            | "/agents/{agent_id}/disable"
            | "/agents/{agent_id}/enable"
            | "/agents/{agent_id}/billing-mode"
            | "/agents/{agent_id}/credential-holder"
            | "/agents/{agent_id}/tool-class"
            | "/agents/{agent_id}/webhooks"
            | "/agents/me/heartbeat"
            | "/agents/me/consumers/{consumer}"
            | "/agents/me/consumers/{consumer}/events"
            | "/agents/me/consumers/{consumer}/ack"
            | "/agents/me/channels"
            | "/agents/me/channels/{channel_id}/config"
            | "/agents/me/triggerers"
            | "/runs"
            | "/runs/{run_id}"
            | "/runs/{run_id}/steps"
            | "/runs/{run_id}/context"
            | "/runs/{run_id}/start"
            | "/runs/{run_id}/resume"
            | "/runs/{run_id}/invocation-token"
            | "/runs/{run_id}/await-input"
            | "/runs/{run_id}/finish"
            | "/runs/{run_id}/cancel"
            | "/channels/{channel_id}/commands"
            | "/commands"
            | "/commands/{command_id}"
            | "/channels/{channel_id}/commands/{command_id}/autocomplete"
            | "/channels/{channel_id}/commands/{command_id}/invoke"
            | "/command-autocompletions/{request_id}/answer"
            | "/apps"
            | "/app-manifests/validate"
            | "/apps/{app_id}"
            | "/apps/{app_id}/manifest"
            | "/apps/{app_id}/scopes"
            | "/apps/{app_id}/suspend"
            | "/apps/{app_id}/resume"
            | "/apps/{app_id}/uninstall"
            | "/apps/{app_id}/webhooks"
            | "/webhooks/{subscription_id}"
            | "/webhooks/{subscription_id}/deliveries"
            | "/webhook-deliveries/{delivery_id}/redeliver"
            | "/audit/events"
            | "/audit/export"
            | "/audit/verify"
            | "/stats/usage"
            | "/stats/runs"
            | "/stats/tool-calls"
            | "/stats/errors"
            | "/stats/costs"
            | "/stats/live"
            | "/stats/timeline"
            | "/stats/slo"
            | "/stats/backends"
            | "/prices"
            | "/prices/{price_id}/close"
            | "/costs/reconcile"
            | "/costs/reconciliations"
            | "/costs/estimates"
            | "/status"
            | "/status/public"
            | "/status/components"
            | "/status/components/{component_id}"
            | "/status/incidents"
            | "/status/incidents/{incident_id}/updates"
            | "/imports"
            | "/imports/{import_id}"
            | "/imports/{import_id}/items"
            | "/imports/{import_id}/start"
            | "/imports/{import_id}/pause"
            | "/imports/{import_id}/cancel"
            | "/imports/{import_id}/complete"
            | "/imports/{import_id}/leads"
            | "/imports/{import_id}/batches"
            | "/imports/{import_id}/files"
            | "/imports/{import_id}/files/{file_id}/parts/{part_number}"
            | "/imports/{import_id}/files/{file_id}/complete"
            | "/imports/{import_id}/cursor"
            | "/gdpr-requests"
            | "/gdpr-requests/{request_id}"
            | "/gdpr-requests/{request_id}/decide"
            | "/gdpr-requests/{request_id}/export"
            | "/hosts"
            | "/hosts/pair"
            | "/hosts/{host_id}"
            | "/hosts/{host_id}/pairing-code"
            | "/hosts/{host_id}/confirm"
            | "/hosts/{host_id}/llm-credentials"
            | "/hosts/{host_id}/state"
            | "/hosts/{host_id}/terminal/sessions"
            | "/terminal/sessions"
            | "/terminal/sessions/{session_id}"
            | "/terminal/sessions/{session_id}/attach"
            | "/terminal/sessions/{session_id}/close"

      Parameters

      • method: M

        post, put, patch or delete.

      • path: P

        The path template of the operation, for example /commands.

      • init: MaybeOptionalInit<paths[P], M>

        Its parameters and body as openapi-fetch takes them (plain JSON).

      • options: CallOptions

        The thread whose order it keeps and the run.

      Returns Promise<OutboxEntry>

      The entry after the send attempt.

      TypeError before storing for a value that is not plain JSON or a header the outbox owns (Idempotency-Key) or that carries a credential; an error of the store.

      await outbox.call("post", "/commands", { body: { name: "status", description: "Status" } }, {
      threadId,
      });
    • Returns every entry that failed permanently.

      Returns Promise<OutboxEntry[]>

      The failed entries in order.

    • Sends every pending entry again, in order per thread, threads in parallel.

      Returns Promise<void>

      When every thread was drained up to its first transient failure.

    • Stores a reply with a new client_msg_id and sends it (createMessage).

      Parameters

      • threadId: string

        The thread.

      • contentMd: string

        The Markdown text.

      • options: SendMessageOptions = {}

        Run, the message it answers, kind and components.

      Returns Promise<OutboxEntry>

      The entry after the send attempt (sent, failed or still pending).

      RangeError before storing when the components break the limits of component.max_per_message or component.custom_id_max_chars; an error of the store.