Set up your destination
- Open Library → Agent Chats → Set up Agent Chats in the destination workspace. Ask an administrator if Agent Chats is unavailable.
- Create an application, such as Support assistant, with a stable key, such as
support-agent. - Set its access policy, content capture, redaction, retention, and allowed environments before sending customer data.
- Create an ingest credential. Save the secret when it appears. BuildBetter shows it once.
Use an application key and credential created in the destination environment. The credential selects the workspace.
context.environment describes your source environment and does not select the destination.
Enabling Agent Chats does not connect any agent automatically. Customers connect their own agents to their own workspaces. It does not grant access to another workspace’s chats.
Start with HTTP
The HTTP API works from any language. Send a server-sidePOST to /v3/rest/agent-conversations/ingest with:
- Header
X-BuildBetter-Agent-Key: your ingest secret. - Header
Content-Type:application/json. - Body
agentKey: your application’s stable key. - Body
externalSessionId: your conversation ID. - Body
events: messages or feedback with stable event IDs, sequences, and timestamps.
Node SDK preview
The preview requires Node.js 22.12 or later. The root package supports ESM and CommonJS. This example uses ESM. The variables below represent server configuration. Set the secret outside your source code.user.id maps to the HTTP field externalId, and user.name maps to displayName. External identities do not create BuildBetter users or Persons.
Identity and properties
Send the identity from your authenticated server. Do not trust an ID supplied by an unauthenticated browser.
The same participant fields work inside
participants[]. The user shortcut also attributes user messages to that participant unless a message supplies participantId.
Each properties object accepts up to 50 keys. Keys contain 1–80 characters. Values can be strings, finite numbers, booleans, null, arrays, or JSON objects.
Company IDs are retained with the conversation. They do not create companies, link CRM company records, or provide PostHog-style group profiles. Person matching does not create people. If an email matches multiple people, BuildBetter does not choose one. Configure existing CRM records separately when you need canonical associations.
SDK field reference
Client options
Conversation and message fields
An empty assistant message with an explicit odd sequence and
final: false reserves a position without content. Reuse its ID and sequence when the response finishes. Increase its revision.
capture(), feedback(), and ingest() return the BuildBetter session UUID, accepted/deduplicated/revised event counts, and processingStatus. They also return batchCount and each transmitted event’s ID and sequence. An accepted batch is not proof of completed analysis.
Add thumbs-up, thumbs-down, or written feedback
Send feedback from your authenticated server after it verifies that the user can access the target message. For the assistant response above:positive for a good response and negative for a bad response. Supply at least one rating, label, or comment. messageSequence is the target assistant’s sequence, not the feedback sequence.
The preview SDK keeps one feedback event per target message. Increase revision when that feedback changes. Independent votes from multiple people require distinct feedback events through the HTTP API.
Explicit feedback creates a Signal without model credits. Qualitative analysis of finalized assistant responses uses response credits. Use the Agent Chat source filters in Signals to separate explicit feedback from inferred findings.
Vercel AI SDK preview
The optional wrapper supports Vercel AI SDK 7 (ai@^7.0.0) and uses the ESM subpath @buildbetter/ai/vercel. Your provider package must support that AI SDK version.
turnId, a positive odd turnSequence, and turnStartedAt before generation. Reuse them on retries and tool steps. Supply the message maps by zero-based visible history position. Increase a message’s revision when you edit it.
Await each call for a session before the next call. Consume or cancel a response stream before another call. The wrapper rejects overlapping calls for the same destination and session within a process. Coordinate sessions across processes in your application.
For the simplest integration, use capture() after saving finalized messages. Use the wrapper when you need model-level capture and can supply stable turn metadata. Do not combine wrapper capture and direct capture for the same session.
Delivery and retries
- Persist message IDs, sequences, revisions, and timestamps before sending. Reuse them for retries.
- Increase
revisionwhen an existing event changes. Keep its sequence and type unchanged. - With the SDK, send new messages with explicit odd sequences. Do not mix raw HTTP event numbering with SDK numbering in one session.
- Send
status: "ended"or"abandoned"when the conversation ends. Include at least one event, such as a replay of the final message. - Await delivery before the process exits. Use a durable server queue when delivery must survive request or process failures.
- Direct SDK methods throw on failure. They do not provide a durable queue or automatic retries. Retry transient failures with bounded backoff and stable event data.
- The SDK batches requests and truncates oversized visible text. The HTTP limits are 500 events, 2 MiB per request, and 256 KiB per event.
Confirm the integration
- Send a synthetic conversation with a unique session ID and a known surface.
- Confirm the session appears in Library → Agent Chats in the intended workspace.
- Send negative feedback on its assistant response. Confirm the rating and message link.
- Retry the unchanged payload. Confirm the API reports deduplicated events instead of a second conversation.
- Check access with an account outside the application’s allowed users.
processingStatus: "pending" confirms ingestion, not completed signal extraction. Check the conversation after processing finishes.
Before sending real data, review the privacy settings. When ownerUserId is omitted, the application’s access policy controls visibility, with workspace access as the default. For owner-only chats, use an active BuildBetter user UUID from the destination workspace, not an external participant ID.