RODEO

Signal Integration

Reporting observations and feeding the Engine.

Signals report what happened after a touch delivers — delivery, engagement, response, sentiment, conversion. The Engine uses these readings to trigger adjustment rules.

Types

TypeMeasuresMetrics
deliveryMessage arriveddelivered, bounced, blocked
engagementAudience interactedopened, clicked, viewed
responseAudience respondedreplied, called_back, forwarded
behaviorObservable actionsvisited_site, downloaded, shared
sentimentEmotional signalpositive, negative, neutral, hostile
conversionGoal completionsigned, purchased, enrolled

Submitting

await rodeo.signals.report({
  signalId: "twilio-webhook",
  touchId: touch.id,
  sceneId: scene.id,
  type: "delivery",
  metric: "delivered",
  value: true,
  confidence: 1.0,
});

Fields

FieldTypeRequiredDescription
signalIdstringyesSignal source identifier
touchIdUUIDyesTarget touch
sceneIdUUIDyesParent scene
typestringyesSignal type
metricstringyesWhat was measured
valueanyyesMeasurement value
confidencenumbernoReliability, 0.0--1.0 (default 1.0)

Batch

await rodeo.signals.reportBatch([
  { signalId: "twilio-webhook", touchId: touch.id, sceneId: scene.id, type: "delivery", metric: "delivered", value: true },
  { signalId: "twilio-webhook", touchId: touch.id, sceneId: scene.id, type: "response", metric: "replied", value: "Sounds interesting" },
  { signalId: "sentiment-analyzer", touchId: touch.id, sceneId: scene.id, type: "sentiment", metric: "positive", value: 0.85, confidence: 0.72 },
]);

Webhook pattern

app.post("/webhooks/twilio", async (req, res) => {
  const { MessageSid, MessageStatus } = req.body;
  const touch = await findTouchByProviderRef(MessageSid);
  if (!touch) return res.sendStatus(200);

  await rodeo.signals.report({
    signalId: "twilio-delivery",
    touchId: touch.id,
    sceneId: touch.sceneId,
    type: "delivery",
    metric: MessageStatus,
    value: MessageStatus === "delivered",
  });

  res.sendStatus(200);
});

Confidence

RangeSignal
1.0Direct observation (webhook, API response)
0.7--0.9Inferred (open tracking, behavioral)
0.3--0.6Estimated (sentiment analysis, prediction)
< 0.3Speculative

The Engine weighs readings by confidence when evaluating adjustment rules.

Querying

const scene = await rodeo.scenes.get(sceneId);
// scene.signal_readings contains all readings