Skip to main content
A scenario holds the situation a run was in: the trigger that started it and the data available when it arrived. Bitfab can read the trigger from a trace, but the records your agent could see (messages, contacts, memories, calendar events) live in your systems. The scenario callback lets your code send them. Each time a trace is added to a dataset, Bitfab sends the trace to one URL you choose. Your code looks up what it holds for that run and answers with it, and Bitfab saves the answer onto the trace’s scenario.

Setup

  1. Go to Integrations in the Bitfab portal.
  2. Under Scenarios, click Connect on the Scenario callback card.
  3. Enter the URL Bitfab should send to (https only) and a Signing secret of at least 16 characters.
  4. Click Save, then Test Connection. Bitfab sends a ping, and any 2xx answer passes.
There is one callback per organization. Every request names its trace function, so one endpoint can handle several functions.

The request

Bitfab sends a POST with a JSON body:
scenario.trigger and scenario.data are null when the scenario has not been generated yet. rootSpan is null when the trace has no root span. environment is the environment the trace was recorded in, or null. callerMetadata is the metadata your code attached to the trace, {} when there is none.

When Bitfab does not send

Bitfab sends once per trace added to a dataset, and skips the trace when:
  • the trace is a replay. Its scenario belongs on the trace it replays;
  • Bitfab builds the trigger for this trace function and it came out empty. Nothing is saved, so the scenario keeps showing the trace’s input and output.
Adding a trace to a second dataset sends it again, and the answer is saved the same way as the first. The test ping has a smaller body: { "type": "ping", "version": 1, "organizationId": "..." }. Bitfab may add fields to the request, and new type values, without raising version, so ignore the ones you do not know. version goes up only when a field you already read changes shape or meaning.

Verifying the signature

Every request carries a Bitfab-Signature header:
v1 is the hex HMAC-SHA256 of <t>.<raw body>, keyed with your signing secret. Compute it over the raw body before parsing it, compare it in constant time, and reject requests whose t is more than a few minutes old.

The answer

Answer 200 with a JSON object, or 204 when you have nothing to add. Every field is optional, and a field you leave out is left as it is. A field Bitfab does not know is refused, so a misspelled field fails loudly instead of being dropped. A record looks like this:
kind is any name for the kind of record your systems hold, such as memory, order, or ticket. ref names the record in your systems. at is when it was written, or null. asOf is run when the record is as it was when the run started, and now when it is as it is today. quote is the exact text Bitfab looks for in the run’s spans, falling back to text when it is null.

The trigger

scenario.trigger is null until a trigger is saved, and records are refused until one is. Send it in the same answer as the records. History, missing items, and the actual outcome can be saved without a trigger, and the trigger stays unset until an answer sends one. Every field is required:

History and sources

A history entry is one earlier fact, in time order:
role is thread start for the message that opened the thread and fact for anything else. sources describes how a captured copy of your systems was read. Its shape is specific to captures Bitfab already reads, so leave it out unless Bitfab has asked you to send it.

Merge or replace

Leave mode out, or send merge, to add to what the scenario holds. Send replace when your answer is the full picture: each of records, history, and missing that you send replaces the saved one whole, so an empty list clears it. A list you leave out is kept in either mode, so { "mode": "replace", "records": [] } clears the records and nothing else. Repeats inside one answer are dropped in both modes: identical records, history entries with the same kind and quote, and the same missing text. In merge mode, sending the same answer twice leaves the scenario as it was after the first. Describe the situation only. A scenario is read by the person who labels the run, so never say what the run should have done.

Failures

Bitfab waits up to 60 seconds for an answer. A timeout or a non-2xx answer is retried up to three times. An answer that is not JSON, or does not match the shape above, is not retried. The run’s error names the field that was refused.