Core Concepts

Outcome Reporting

Help AMP learn by reporting what happened after each interaction.

Why Report Outcomes?

Outcome reporting is how AMP learns what works for each user. Without outcomes, AMP can't improve its recommendations.

Without Outcomes

  • ❌ AMP uses population defaults forever
  • ❌ No personalisation happens
  • ❌ Recommendations stay generic
  • ❌ Wasted potential

With Outcomes

  • ✅ AMP learns user preferences
  • ✅ Recommendations improve over time
  • ✅ Completion rates increase
  • ✅ Users are more engaged

The reportOutcome() Call

After a user interacts with your agent's response, report what happened:

await amp.reportOutcome({
  requestId: context.requestId,  // From getContext() response
  started: true,                  // Did user start the task?
  completed: true,                // Did they complete it?
  timeToStart: 45,               // Optional: seconds until started
  flowState: true,                // Optional: were they engaged?
  satisfaction: 0.9,             // Optional: explicit feedback (0-1)
});

Required Parameters

ParameterTypeDescription
requestIdstringThe ID from getContext() response
startedbooleanDid the user start working on the task?

Optional Parameters

ParameterTypeDescription
completedbooleanDid they complete the task?
timeToStartnumberSeconds from response to starting (lower is better)
flowStatebooleanDid they seem deeply engaged? (in flow)
satisfactionnumberExplicit user feedback score (0-1)
metadataobjectAdditional context about the outcome

Outcome Patterns

Pattern 1: Successful Completion

// User started immediately and completed successfully
await amp.reportOutcome({
  requestId: context.requestId,
  started: true,
  completed: true,
  timeToStart: 10,
  flowState: true,
  satisfaction: 0.95
});

// AMP learns: This approach worked really well

Pattern 2: Started But Not Completed

// User started but got stuck or gave up
await amp.reportOutcome({
  requestId: context.requestId,
  started: true,
  completed: false,
  timeToStart: 30,
  flowState: false
});

// AMP learns: This approach wasn't quite right

Pattern 3: Never Started

// User didn't even start the task
await amp.reportOutcome({
  requestId: context.requestId,
  started: false,
  completed: false
});

// AMP learns: This approach didn't motivate the user at all

Pattern 4: Delayed Start

// User hesitated but eventually started and completed
await amp.reportOutcome({
  requestId: context.requestId,
  started: true,
  completed: true,
  timeToStart: 300,  // 5 minutes delay
  flowState: false
});

// AMP learns: Approach worked but wasn't immediately motivating

When to Report Outcomes

Immediate vs Delayed Reporting

You can report outcomes immediately or after a delay:

// Option 1: Immediate (optimistic)
const context = await amp.getContext({ userId, task });
const response = await generateResponse(context);

// Assume success and report immediately
await amp.reportOutcome({
  requestId: context.requestId,
  started: true,
  completed: true  // Optimistic assumption
});

// Option 2: Delayed (accurate)
const context = await amp.getContext({ userId, task });
const response = await generateResponse(context);

// Wait for actual user behaviour
setTimeout(async () => {
  const actualOutcome = await trackUserBehaviour();
  await amp.reportOutcome({
    requestId: context.requestId,
    ...actualOutcome
  });
}, 60000);  // 1 minute delay

Background Reporting

Report outcomes in the background to avoid blocking:

// Don't await - fire and forget
amp.reportOutcome({
  requestId: context.requestId,
  started: true,
  completed: userCompletedTask
}).catch(err => {
  // Log errors but don't fail the main flow
  console.error('Outcome reporting failed:', err);
});

Tracking User Behaviour

Detecting If User Started

// Track if user took action after response
const userActivity = {
  started: false,
  completed: false,
  timeToStart: null
};

const startTime = Date.now();

// Listen for user actions
on('user:action', () => {
  if (!userActivity.started) {
    userActivity.started = true;
    userActivity.timeToStart = (Date.now() - startTime) / 1000;
  }
});

// Check completion
on('task:complete', () => {
  userActivity.completed = true;
});

Detecting Flow State

// Heuristics for detecting flow state
function detectFlowState(userSession) {
  const indicators = {
    // Continuous activity without long pauses
    continuousActivity: userSession.longestPause < 30,

    // High interaction rate
    highInteractionRate: userSession.actionsPerMinute > 3,

    // Minimal context switching
    focused: userSession.tabSwitches < 2,

    // Quick responses to prompts
    quickResponses: userSession.avgResponseTime < 10
  };

  // Flow state if most indicators are true
  const flowScore = Object.values(indicators)
    .filter(v => v).length / Object.keys(indicators).length;

  return flowScore > 0.7;
}

Gathering Satisfaction Scores

// Ask for explicit feedback
const feedback = await askUser({
  question: "How helpful was this response?",
  scale: "1-5 stars"
});

await amp.reportOutcome({
  requestId: context.requestId,
  started: true,
  completed: true,
  satisfaction: feedback.rating / 5  // Normalize to 0-1
});

Outcome Weights

Not all outcomes are weighted equally in AMP's learning:

OutcomeSignal StrengthImpact
Never startedStrong negativeDecreases confidence in approach
Started + CompletedStrong positiveIncreases confidence in approach
Started + Not CompletedWeak negativeSlight decrease in confidence
Flow State = trueBonus positiveExtra confidence boost
Low timeToStartPositive modifierIndicates strong motivation

Best Practices

Do ✅

  • Always report outcomes, even negative ones
  • Track real user behaviour, not assumptions
  • Include optional parameters when available
  • Report outcomes even for failed interactions
  • Use background reporting to avoid blocking

Don't ❌

  • Report overly optimistic outcomes
  • Skip reporting when outcomes are bad
  • Report before user has chance to act
  • Block main flow waiting for outcome calls
  • Report outcomes for wrong requestId

Error Handling

try {
  await amp.reportOutcome({
    requestId: context.requestId,
    started: userStarted,
    completed: userCompleted
  });
} catch (error) {
  // Log but don't fail
  console.error('Failed to report outcome:', error);

  // Optionally queue for retry
  outcomeQueue.push({
    requestId: context.requestId,
    outcome: { started: userStarted, completed: userCompleted },
    retries: 0
  });
}

💡 Pro Tip: The more accurate your outcome reporting, the faster AMP learns. Track real user behaviour rather than making optimistic assumptions.

Next Steps