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
| Parameter | Type | Description |
|---|---|---|
| requestId | string | The ID from getContext() response |
| started | boolean | Did the user start working on the task? |
Optional Parameters
| Parameter | Type | Description |
|---|---|---|
| completed | boolean | Did they complete the task? |
| timeToStart | number | Seconds from response to starting (lower is better) |
| flowState | boolean | Did they seem deeply engaged? (in flow) |
| satisfaction | number | Explicit user feedback score (0-1) |
| metadata | object | Additional 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 wellPattern 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 rightPattern 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 allPattern 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 motivatingWhen 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 delayBackground 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:
| Outcome | Signal Strength | Impact |
|---|---|---|
| Never started | Strong negative | Decreases confidence in approach |
| Started + Completed | Strong positive | Increases confidence in approach |
| Started + Not Completed | Weak negative | Slight decrease in confidence |
| Flow State = true | Bonus positive | Extra confidence boost |
| Low timeToStart | Positive modifier | Indicates 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.