/

Adaptive Motivation Protocol

Stop Building Personalisation.
Start Using It.

One API Call. 80% Less Code. 34% Better Engagement.

0%
Engagement
0%
Less Code
<0ms
Response

Your AI Agent Has a Personalisation Problem

The Hard Way ❌

Current approach

Build RAG Systems
Bloat System Prompts (2000+ Tokens)
Engineer Prompts for Edge Cases
Manual Effectiveness Tracking
Pay for Bloated Contexts
Maintain Complex Code

Result: Expensive. Fragile. Mediocre.

The AMP Way ✅

Modern approach

One API Call → Structured Context
Lean Prompts (Minimal Tokens)
Automatic Learning
Measured Results
Lower Costs
Clean Codebase

Result: Better Engagement. Cleaner Code.

Before AMP vs After AMP

Replace 300 Lines of Fragile Code with 3 Lines of Reliable Infrastructure

Before: Complex & Fragile

RAG Systems, Bloated Prompts, Manual Tracking

old-approach.tstypescript
1// Before AMP: The Messy Way
2
3// Build RAG for user data
4const embeddings = await openai.embeddings.create({
5 input: userHistory,
6 model: "text-embedding-3-small"
7});
8
9await pinecone.upsert({
10 userId,
11 vectors: embeddings.data
12});
13
14// Retrieve on every request
15const userContext = await pinecone.query({
16 userId,
17 topK: 10
18});
19
20// Bloat your system prompt
21const systemPrompt = `
22 User preferences: ${userContext.matches.map(m => m.metadata).join('\n')}
23 User history: ${userHistory}
24 Communication style: ${inferredStyle}
25 ... [2000 tokens of prompt engineering]
26`;
27
28// Hope it works
29const response = await ai.generate({
30 system: systemPrompt,
31 messages: userQuery
32});
33
34// Manually track outcomes (maybe?)
35if (userCompleted) {
36 await db.update({userId, completionRate: ...});
37}
38
39// Total: 300+ lines of code
40// Cost: 2000+ tokens per request
41// Maintenance: Constant prompt tuning

After: Simple & Powerful

One API Call, Automatic Learning, Clean Code

with-amp.tstypescript
1// After AMP: The Clean Way
2
3import { AMP } from '@amp-protocol/client';
4const amp = new AMP(process.env.AMP_KEY);
5
6// Get personalization context
7const context = await amp.getContext({
8 userId: user.id,
9 task: userQuery
10});
11
12// Adapt your response
13const response = adapt(userQuery, context);
14
15// Report outcome (AMP learns automatically)
16await amp.reportOutcome({
17 requestId: context.requestId,
18 started: true,
19 completed: true
20});
21
22// Total: 3 lines of code
23// Cost: Minimal tokens
24// Maintenance: Zero

Surgical Personalisation in 3 Steps

Add Motivation Intelligence to Your AI Agent in Minutes

Step 1

Your Agent Calls AMP

Sends User ID and Task Context

Step 2

AMP Returns Context

Structured Personalisation Data, Not Bloated Prompts

📈
Step 3

AMP Learns Automatically

Tracks Outcomes, Updates Effectiveness, Improves Over Time

Real Results

0%
Engagement
0%
Completion
0%
Churn
We Integrated AMP in One Day. After 30 Days, Task Completion Increased 41%. The Difference? AMP Learns What Actually Matters.
Sarah Chen
Head of Product, DevTools Inc
View Full Case Study

Add AMP to Your Agent in 5 Minutes

Clean Integration That Works with Any AI Agent Framework

agent-integration.tstypescript
1import { AMP } from '@amp-protocol/client';
2
3const amp = new AMP({
4 apiKey: process.env.AMP_KEY
5});
6
7// Before responding to user
8const context = await amp.getContext({
9 userId: user.id,
10 task: userQuery,
11 metadata: {
12 timestamp: Date.now(),
13 source: 'chat'
14 }
15});
16
17// Context returns:
18// {
19// suggestedFraming: "micro_task",
20// communicationStyle: "brief_directive",
21// complexity: "break_into_steps",
22// effectiveness: 0.87
23// }
24
25// Use it to adapt your response
26const systemPrompt = `You are a coding assistant.
27Use ${context.communicationStyle} communication.
28Frame this as a ${context.suggestedFraming}.`;
29
30// Or adapt programmatically
31const response = adaptResponse(userQuery, context);
32
33// Report the outcome
34await amp.reportOutcome({
35 requestId: context.requestId,
36 started: true,
37 completed: true,
38 timeToStart: 45, // seconds
39 flowState: true,
40 satisfaction: 0.9
41});
42
43// AMP learns and improves automatically

Start Free. Scale as You Grow.

Usage-Based Pricing That Grows with Your Product

Free Forever

Perfect for Testing

$0/month
  • 10,000 API Calls/Month
  • Email Support
  • Full API Access
  • Community Support
Popular

Startup

For Growing Products

$99/month
  • 100,000 Calls/Month
  • Priority Email Support
  • Analytics Dashboard
  • Custom Integrations

Growth

For Scaling Teams

$499/month
  • 1M Calls/Month
  • Slack Support
  • Advanced Analytics
  • Dedicated Onboarding

Enterprise

For Large Organisations

Custom
  • 10M+ Calls/Month
  • Dedicated Support
  • SLA Guarantees
  • Self-Hosted Option

Full Documentation

Complete developer documentation — one document, zero navigation.

47,454 characters

AMP Protocol — Developer Documentation

Complete reference for building motivation-aware AI agents with the Adaptive Motivation Protocol.


Table of Contents

Getting Started

Core Concepts

API Reference

Guides

SDK Reference


=== GETTING STARTED ===

Introduction

The Adaptive Motivation Protocol (AMP) is a lightweight API that gives your AI agents the ability to understand and adapt to individual user motivation patterns. Instead of building complex personalisation logic yourself, AMP learns what works for each user and provides structured context for every interaction.

Why AMP?

Building effective AI agents requires understanding not just what users want, but how they want to receive it. Traditional approaches require:

  • Complex prompt engineering for different user types
  • Manual tracking of user preferences and behaviour
  • Custom A/B testing infrastructure
  • Constant iteration on communication styles

AMP replaces all of this with two simple API calls:

\\\`typescript // 1. Get context before responding const context = await amp.getContext({ userId: user.id, task: userQuery, });

// 2. Report the outcome await amp.reportOutcome({ requestId: context.requestId, started: true, completed: true, }); \\\`

Key Benefits

BenefitDescription
80% Less CodeReplace hundreds of lines of personalisation logic with one API call
34% Better EngagementAMP learns what actually drives each user to complete tasks
Automatic LearningNo manual tuning required. AMP improves with every interaction
Framework AgnosticWorks with any AI agent framework or custom implementation

How It Works

AMP uses behavioural science and machine learning to build motivation profiles for each user:

  1. Context Request — Before your agent responds, call \getContext()\ with the user ID and task description
  2. Structured Guidance — AMP returns communication style recommendations, complexity preferences, and framing suggestions
  3. Adapted Response — Your agent uses this context to personalise its response
  4. Outcome Reporting — Report whether the user started, completed, or abandoned the task
  5. Continuous Learning — AMP updates the user's profile, improving future recommendations

Next Steps

Follow the Quick Start guide to integrate AMP in 5 minutes.


Quick Start

Get AMP integrated into your AI agent in 5 minutes.

1. Get Your API Key

Sign up at amp-protocol.dev and generate an API key from the dashboard.

2. Install the SDK

\\\`bash

TypeScript / JavaScript

npm install @amp-protocol/client

Python

pip install amp-protocol \\\`

3. Initialize the Client

\\\`typescript import { AMP } from '@amp-protocol/client';

const amp = new AMP({ apiKey: process.env.AMP_API_KEY, }); \\\`

4. Get Context Before Responding

\\\`typescript const context = await amp.getContext({ userId: user.id, task: "build a login page", metadata: { timestamp: Date.now(), source: "chat", }, });

// Response includes: // { // requestId: "req_abc123", // suggestedFraming: "micro_task", // communicationStyle: "brief_directive", // complexity: "break_into_steps", // confidence: 0.87 // } \\\`

5. Adapt Your Response

\\\typescript const systemPrompt = \You are a helpful coding assistant. Communication style: ${context.communicationStyle} Task framing: ${context.suggestedFraming} Complexity approach: ${context.complexity}\`;

const response = await llm.generate({ system: systemPrompt, user: userQuery, }); \\\`

6. Report the Outcome

\\\typescript await amp.reportOutcome({ requestId: context.requestId, started: true, completed: true, timeToStart: 45, satisfaction: 0.9, }); \\\

Complete Example

\\\`typescript import { AMP } from '@amp-protocol/client';

const amp = new AMP({ apiKey: process.env.AMP_API_KEY });

export async function handleUserRequest( userId: string, query: string ): Promise<string> { // 1. Get motivation context const context = await amp.getContext({ userId, task: query, metadata: { timestamp: Date.now() }, });

// 2. Build adapted system prompt const systemPrompt = \You are a helpful assistant. Communication style: ${context.communicationStyle} Task framing: ${context.suggestedFraming} Complexity approach: ${context.complexity}\;

// 3. Generate response const response = await llm.generate({ system: systemPrompt, user: query, });

// 4. Report outcome in background amp.reportOutcome({ requestId: context.requestId, started: true, completed: true, }).catch(console.error);

return response; } \\\`


Installation

Prerequisites

  • Node.js 16+ for TypeScript/JavaScript
  • Python 3.8+ for Python
  • An AMP API key from the dashboard

TypeScript / JavaScript

\\\`bash

npm

npm install @amp-protocol/client

yarn

yarn add @amp-protocol/client

pnpm

pnpm add @amp-protocol/client \\\`

Verify installation:

\\\`typescript import { AMP } from '@amp-protocol/client';

const amp = new AMP({ apiKey: process.env.AMP_API_KEY, }); console.log('AMP client initialized'); \\\`

Python

\\\`bash

pip

pip install amp-protocol

poetry

poetry add amp-protocol \\\`

Verify installation:

\\\`python from amp_protocol import AMP import os

amp = AMP(api_key=os.environ.get("AMP_API_KEY")) print("AMP client initialized") \\\`

REST API (Direct)

No SDK required. Use any HTTP client against the base URL:

\\\ https://api.amp-protocol.dev/v1 \\\

\\\bash curl https://api.amp-protocol.dev/v1/context \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "userId": "user_123", "task": "build a login page" }' \\\

Framework Integration Guides

FrameworkSetup
Next.jsImport SDK in API routes or server components. Use env vars for the key.
ExpressInitialize once at app startup, call per-request in route handlers.
FastAPIAsync client with \await amp.get_context()\. Initialize at module level.
LangChainWrap AMP calls in a custom tool or chain step.

Environment Variables

\\\`bash

.env

AMP_API_KEY=amp_sk_live_your_secret_key_here \\\`

Security: Never commit API keys to version control. Use environment variables or a secrets manager.


Authentication

API Key Format

\\\ amp_sk_live_1234567890abcdef \\\

SegmentMeaning
\amp_\AMP protocol identifier
\sk_\Secret key
\live_\ or \test_\Environment (production or sandbox)
RemainderUnique credential

Getting Your API Key

  1. Sign up at amp-protocol.dev
  2. Navigate to the API Keys section in your dashboard
  3. Click "Generate New Key"
  4. Copy and store the key securely (it is shown only once)

Using Your API Key

TypeScript: \\\`typescript import { AMP } from '@amp-protocol/client';

const amp = new AMP({ apiKey: process.env.AMP_API_KEY, }); \\\`

Python: \\\`python from amp_protocol import AMP import os

amp = AMP(api_key=os.environ.get("AMP_API_KEY")) \\\`

REST: \\\bash curl https://api.amp-protocol.dev/v1/context \ -H "Authorization: Bearer amp_sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"userId": "user_123", "task": "complete the report"}' \\\

Test Mode vs Live Mode

EnvironmentKey PrefixBehaviour
Test\amp_sk_test_\Free unlimited requests, isolated sandbox, profiles reset monthly
Live\amp_sk_live_\Production data, real profiles, metered billing

Rate Limits

PlanRequests/SecondMonthly Limit
Starter10 req/s100,000
Pro100 req/s1,000,000
EnterpriseCustomUnlimited

Key Rotation

Rotate keys every 90 days. Generate a new key before revoking the old one to avoid downtime.

Troubleshooting

ErrorCauseFix
\401 Unauthorized\Invalid or missing API keyVerify the key is correct and the \Authorization\ header is set
\403 Forbidden\Key lacks permissionsCheck key permissions in dashboard
\429 Too Many Requests\Rate limit exceededImplement exponential backoff or upgrade your plan

=== CORE CONCEPTS ===

How AMP Works

The Core Problem

Every user is different. Some prefer step-by-step guidance, others want the full solution up front. Some respond to encouragement, others find it distracting. Building personalised motivation logic from scratch is expensive and brittle.

The AMP Learning Loop

AMP automatically learns what motivates each user through a continuous feedback loop:

  1. Context Request — Call \getContext()\ with the user ID and task description
  2. Structured Guidance — AMP returns communication style, complexity preferences, and framing recommendations
  3. Adapted Response — Your agent uses this context to personalise its output
  4. Outcome Reporting — Report whether the user started, completed, or abandoned the task
  5. Model Update — AMP refines the user's motivation profile for future interactions

Example Flow

\\\`typescript // User asks: "Help me refactor the auth module"

// Step 1: Get context const context = await amp.getContext({ userId: "user_42", task: "refactor auth module", taskType: "coding", complexity: "high", });

// Step 2: AMP responds with personalised guidance // context.suggestedFraming === "micro_task" // context.communicationStyle === "brief_directive" // context.complexity === "break_into_steps" // context.confidence === 0.82

// Step 3: Agent uses context to adapt its response const systemPrompt = \Break this into small steps. Be concise and direct.\;

// Step 4: Report outcome await amp.reportOutcome({ requestId: context.requestId, started: true, completed: true, timeToStart: 30, }); \\\`

Motivation Dimensions

AMP analyses four behavioural dimensions:

Task Framing — How to present the work:

TypeDescriptionBest For
AchievementGoal-oriented framingUsers who track progress and milestones
LearningExploration-oriented framingUsers motivated by understanding
Micro-taskSmall incremental stepsUsers who feel overwhelmed by large tasks
ChallengePuzzle/problem framingUsers who enjoy competition and difficulty

Communication Style — How to deliver information:

StyleDescription
Brief DirectiveShort, direct instructions
Detailed ExplanatoryFull context with reasoning
ConversationalFriendly, encouraging tone
TechnicalPrecise, jargon-heavy

Complexity Handling — How much detail to provide:

LevelDescription
Full SolutionComplete working code/answer
Break Into StepsGuided step-by-step process
Hints OnlyDirectional clues without full answers
High LevelConceptual overview

Encouragement Level — How much positive reinforcement:

LevelDescription
HighFrequent encouragement and praise
ModerateBalanced feedback
MinimalResults-focused with little commentary
NonePure information exchange

The ML Model

AMP uses a multi-armed bandit approach combined with collaborative filtering:

  • Cold Start (0-5 interactions) — Population-level defaults, low confidence (0.2-0.4). AMP explores different approaches.
  • Learning (5-20 interactions) — Patterns emerge, confidence increases (0.5-0.7). Recommendations become personalised.
  • Optimised (20+ interactions) — High-confidence recommendations (0.7-0.95). Occasional exploration to adapt to changing preferences.

Privacy

AMP stores behavioural patterns only — never task content or PII. User IDs are hashed. All data encrypted at rest and in transit. Full GDPR/CCPA compliance.


Motivation Profiles

A motivation profile is a dynamic, multi-dimensional model of a user's behavioural preferences. Profiles evolve continuously based on real interaction data.

Profile Structure

\\\`typescript interface MotivationProfile { userId: string;

// Behavioural preferences preferredFraming: FramingType; communicationStyle: CommunicationStyle; complexityPreference: ComplexityLevel; encouragementLevel: EncouragementLevel;

// Performance metrics totalInteractions: number; completionRate: number; averageTimeToStart: number; // seconds flowStateFrequency: number; // 0-1

// Confidence scores (0-1) framingConfidence: number; styleConfidence: number; complexityConfidence: number;

// Contextual patterns taskTypeAffinities: Record<string, number>; timeOfDayPatterns: TimePattern[]; } \\\`

Profile Evolution Phases

PhaseInteractionsConfidenceBehaviour
Cold Start0-50.2-0.4Population defaults, active exploration
Learning5-200.5-0.7Patterns emerging, increasing personalisation
Optimised20+0.7-0.95Stable preferences, occasional exploration

Framing Types

TypeExample Prompt
Achievement"Complete this feature to hit your weekly milestone"
Learning"Explore how OAuth works by building this flow"
Micro-task"Start by just creating the function signature"
Challenge"Can you implement this without using any external libraries?"

Multi-Context Profiles

Users often behave differently depending on the task type. AMP tracks per-context preferences:

\\\typescript // Same user, different contexts { "coding": { preferredFraming: "challenge", communicationStyle: "brief_directive" }, "documentation": { preferredFraming: "micro_task", communicationStyle: "conversational" }, "debugging": { preferredFraming: "micro_task", communicationStyle: "technical" } } \\\

Manual Overrides

Use \updateProfile()\ to set preferences explicitly — for example, when a user fills out an onboarding questionnaire or explicitly states a preference.

\\\typescript await amp.updateProfile({ userId: "user_123", communicationStyle: "brief_directive", encouragementLevel: "minimal", }); \\\

Manual overrides carry higher weight than learned preferences, but AMP continues to adapt based on actual outcomes.


Context API

The Context API is the primary integration point. Call \getContext()\ before your agent generates a response to get personalised recommendations.

The getContext() Call

\\\typescript const context = await amp.getContext({ userId: "user_123", task: "build a login page", complexity: "medium", metadata: { source: "chat", timestamp: Date.now() } }); \\\

Request Parameters

Required:

ParameterTypeDescription
\userId\stringUnique identifier for the user
\task\stringDescription of what the user wants to accomplish

Optional:

ParameterTypeDescription
\complexity\\`"low" \"medium" \"high"\`Helps AMP tailor recommendations
\taskType\stringCategory (e.g., "coding", "writing", "debugging")
\metadata\objectAdditional context (source, timestamp, session info)

Response Structure

\\\typescript { requestId: "req_abc123", suggestedFraming: "micro_task", communicationStyle: "brief_directive", complexity: "break_into_steps", encouragement: "moderate", confidence: 0.87, rationale: "User has 85% completion rate with step-by-step guidance", metadata: { profilePhase: "optimised", interactionCount: 47, explorationMode: false } } \\\

Three Integration Approaches

Approach 1: System Prompt Injection

\\\`typescript const context = await amp.getContext({ userId: user.id, task: userQuery });

const systemPrompt = \You are a helpful coding assistant. Communication: ${context.communicationStyle} Framing: ${context.suggestedFraming} Detail level: ${context.complexity} Encouragement: ${context.encouragement}\; \\\`

Approach 2: Programmatic Branching

\\\`typescript const context = await amp.getContext({ userId: user.id, task: userQuery });

if (context.complexity === "break_into_steps") { response = await generateStepByStep(userQuery); } else if (context.complexity === "hints_only") { response = await generateHints(userQuery); } else { response = await generateFullSolution(userQuery); }

if (context.encouragement === "high") { response = addEncouragement(response); } \\\`

Approach 3: Hybrid (Recommended)

\\\`typescript const context = await amp.getContext({ userId: user.id, task: userQuery });

const systemPrompt = buildSystemPrompt(context); const strategy = selectStrategy(context);

const rawResponse = await llm.generate({ systemPrompt, userQuery, temperature: strategy.temperature });

const finalResponse = postProcess(rawResponse, context); \\\`

Handling Low Confidence

When \context.confidence < 0.5\, AMP is still learning the user. Use a balanced approach:

\\\typescript if (context.confidence < 0.5) { // Hedge: offer multiple approaches response = generateHybridResponse(userQuery); } else { response = generateAdaptedResponse(userQuery, context); } \\\

Caching

Cache context for high-traffic applications, but keep TTL under 5 minutes:

\\\`typescript const cache = new TTLCache({ ttl: 300_000 });

async function getCachedContext(userId: string, task: string) { const key = \${userId}:${hashTask(task)}\; let ctx = cache.get(key); if (!ctx) { ctx = await amp.getContext({ userId, task }); cache.set(key, ctx); } return ctx; } \\\`

Error Handling

Always fall back gracefully if AMP is unavailable:

\\\typescript let context; try { context = await amp.getContext({ userId: user.id, task: userQuery }); } catch (error) { console.warn('AMP unavailable, using defaults:', error); context = { suggestedFraming: 'achievement', communicationStyle: 'conversational', complexity: 'break_into_steps', confidence: 0.5 }; } \\\


Outcome Reporting

Outcome reporting closes the learning loop. Without it, AMP cannot improve its recommendations.

Why Report Outcomes?

Without ReportingWith Reporting
Static population defaultsPersonalised per-user recommendations
No learning over timeContinuous improvement
Generic responsesIncreasing completion rates

The reportOutcome() Call

\\\typescript await amp.reportOutcome({ requestId: context.requestId, // from getContext() started: true, completed: true, timeToStart: 45, // seconds before user began flowState: true, // user was engaged satisfaction: 0.9, // user self-report (0-1) }); \\\

Required vs Optional Parameters

ParameterRequiredTypeDescription
\requestId\YesstringFrom the \getContext()\ response
\started\YesbooleanWhether the user began the task
\completed\NobooleanWhether they finished
\timeToStart\NonumberSeconds before starting
\flowState\NobooleanWhether the user was engaged
\satisfaction\NonumberUser satisfaction (0-1)
\metadata\NoobjectAdditional context

Outcome Patterns

Success: \\\typescript await amp.reportOutcome({ requestId: context.requestId, started: true, completed: true, timeToStart: 10, flowState: true, satisfaction: 0.95 }); \\\

Started but not completed: \\\typescript await amp.reportOutcome({ requestId: context.requestId, started: true, completed: false, timeToStart: 30, flowState: false }); \\\

Never started: \\\typescript await amp.reportOutcome({ requestId: context.requestId, started: false, completed: false }); \\\

Delayed start: \\\typescript await amp.reportOutcome({ requestId: context.requestId, started: true, completed: true, timeToStart: 300, flowState: false }); \\\

Signal Weights

OutcomeSignal StrengthEffect on Profile
Never startedStrong negativeMajor confidence decrease for current approach
Started + CompletedStrong positiveMajor confidence increase
Started + AbandonedWeak negativeMinor adjustment
Flow state detectedBonus positiveExtra confidence boost
Fast time-to-startPositive modifierIndicates strong motivation match

Best Practices

  • Report outcomes for every interaction, including negative ones
  • Report in the background (fire-and-forget) to avoid blocking the user
  • Include optional fields when available for richer learning signals
  • Report based on actual behaviour, not assumptions

=== API REFERENCE ===

getContext()

Request motivation-aware context for a user interaction.

Endpoint

\\\ POST /v1/context \\\

Headers

\\\ Authorization: Bearer amp_sk_live_your_key_here Content-Type: application/json \\\

Request Body

\\\typescript interface GetContextParams { userId: string; // Required. Unique user identifier. task: string; // Required. Task description. complexity?: 'low' | 'medium' | 'high'; // Optional. Task complexity hint. taskType?: string; // Optional. Category (e.g., "coding"). metadata?: Record<string, any>; // Optional. Additional context. } \\\

Response Body

\\\typescript interface MotivationContext { requestId: string; // Unique request ID. Use in reportOutcome(). suggestedFraming: 'achievement' | 'learning' | 'micro_task' | 'challenge'; communicationStyle: 'brief_directive' | 'detailed_explanatory' | 'conversational' | 'technical'; complexity: 'full_solution' | 'break_into_steps' | 'hints_only' | 'high_level'; encouragement: 'high' | 'moderate' | 'minimal' | 'none'; confidence: number; // 0-1. How well AMP knows this user. rationale: string; // Human-readable explanation. metadata: { profilePhase: 'cold_start' | 'learning' | 'optimised'; interactionCount: number; explorationMode: boolean; // true when AMP is trying new approaches }; } \\\

Examples

Basic: \\\typescript const context = await amp.getContext({ userId: 'user_123', task: 'build a login form' }); \\\

With all parameters: \\\typescript const context = await amp.getContext({ userId: 'user_123', task: 'fix authentication bug', complexity: 'high', taskType: 'debugging', metadata: { source: 'slack', priority: 'urgent' } }); \\\

curl: \\\bash curl -X POST https://api.amp-protocol.dev/v1/context \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "userId": "user_123", "task": "build a login page", "complexity": "medium", "taskType": "coding" }' \\\

Error Codes

CodeDescription
\INVALID_USER_ID\User ID is missing or malformed
\INVALID_TASK\Task description is missing or empty
\RATE_LIMIT_EXCEEDED\Too many requests
\UNAUTHORIZED\Invalid API key

reportOutcome()

Report the outcome of an interaction to close the learning loop.

Endpoint

\\\ POST /v1/outcome \\\

Headers

\\\ Authorization: Bearer amp_sk_live_your_key_here Content-Type: application/json \\\

Request Body

\\\typescript interface OutcomeParams { requestId: string; // Required. From getContext() response. started: boolean; // Required. Did the user begin the task? completed?: boolean; // Did they finish? timeToStart?: number; // Seconds before starting. flowState?: boolean; // Was the user engaged? satisfaction?: number; // User self-report (0-1). metadata?: Record<string, any>; } \\\

Response

\\\json { "acknowledged": true, "profileUpdated": true } \\\

Examples

TypeScript: \\\typescript await amp.reportOutcome({ requestId: context.requestId, started: true, completed: true, timeToStart: 15, flowState: true, satisfaction: 0.95 }); \\\

Python: \\\python await amp.report_outcome( request_id=context.request_id, started=True, completed=True, time_to_start=15, flow_state=True, satisfaction=0.95 ) \\\

curl: \\\bash curl -X POST https://api.amp-protocol.dev/v1/outcome \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "requestId": "req_abc123", "started": true, "completed": true, "timeToStart": 15, "flowState": true, "satisfaction": 0.95 }' \\\

Error Codes

CodeDescription
\INVALID_REQUEST_ID\Request ID not found or malformed
\OUTCOME_ALREADY_REPORTED\An outcome was already submitted for this request
\REQUEST_EXPIRED\Request is older than 24 hours

updateProfile()

Manually override or set user profile preferences. Useful for onboarding data, explicit user preferences, or importing from external systems.

Endpoint

\\\ PUT /v1/profile/:userId \\\

Headers

\\\ Authorization: Bearer amp_sk_live_your_key_here Content-Type: application/json \\\

Request Body

\\\typescript interface UpdateProfileParams { userId: string; preferredFraming?: 'achievement' | 'learning' | 'micro_task' | 'challenge'; communicationStyle?: 'brief_directive' | 'detailed_explanatory' | 'conversational' | 'technical'; complexityPreference?: 'full_solution' | 'break_into_steps' | 'hints_only' | 'high_level'; encouragementLevel?: 'high' | 'moderate' | 'minimal' | 'none'; metadata?: Record<string, any>; } \\\

Response

Returns the updated profile:

\\\typescript interface MotivationProfile { userId: string; preferredFraming: FramingType; communicationStyle: CommunicationStyle; complexityPreference: ComplexityLevel; encouragementLevel: EncouragementLevel; totalInteractions: number; completionRate: number; confidence: number; } \\\

Use Cases

User stated preference: \\\typescript // User said: "Just give me the code, no explanations" await amp.updateProfile({ userId: 'user_123', communicationStyle: 'brief_directive', encouragementLevel: 'none' }); \\\

Onboarding questionnaire: \\\typescript await amp.updateProfile({ userId: 'user_123', preferredFraming: onboarding.framingPreference, complexityPreference: onboarding.detailLevel, metadata: { source: 'onboarding', completedAt: Date.now() } }); \\\

Import from another system: \\\typescript await amp.updateProfile({ userId: 'user_123', preferredFraming: legacyProfile.taskFraming, metadata: { imported: true, source: 'legacy_system' } }); \\\

Error Codes

CodeDescription
\INVALID_USER_ID\User ID is missing or malformed
\INVALID_PREFERENCE\One or more preference values are invalid
\UNAUTHORIZED\Invalid API key

Note: Manual overrides carry higher weight than learned preferences, but AMP will still adapt based on actual outcomes over time.


Error Handling

Error Response Format

All API errors follow a consistent structure:

\\\json { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Too many requests. Please retry after 60 seconds.", "details": { "limit": 100, "window": "60s", "retryAfter": 42 }, "requestId": "req_abc123", "timestamp": "2024-01-15T10:30:00Z" } } \\\

Common Error Codes

HTTP StatusCodeDescriptionResolution
400\INVALID_USER_ID\User ID missing or malformedProvide a valid user ID string
400\INVALID_TASK\Task description missing or emptyProvide a descriptive task string
400\INVALID_REQUEST_ID\Request ID not foundUse the requestId from getContext()
400\INVALID_PREFERENCE\Invalid preference valueCheck allowed enum values
401\UNAUTHORIZED\Invalid or missing API keyVerify your API key
403\FORBIDDEN\Insufficient permissionsCheck key permissions in dashboard
404\PROFILE_NOT_FOUND\No profile for this userProfile is created automatically on first getContext()
429\RATE_LIMIT_EXCEEDED\Too many requestsImplement exponential backoff
429\QUOTA_EXCEEDED\Monthly quota reachedUpgrade plan or wait for reset
500\INTERNAL_ERROR\Server errorRetry with backoff. Contact support if persistent.

Retry Strategy

\\\typescript async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> { for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await fn(); } catch (error) { if (error.code === 'RATE_LIMIT_EXCEEDED' && attempt < maxRetries) { const delay = error.details?.retryAfter ? error.details.retryAfter * 1000 : Math.pow(2, attempt) * 1000; await new Promise(r => setTimeout(r, delay)); continue; } throw error; } } throw new Error('Max retries exceeded'); } \\\

Graceful Degradation

Always have a fallback so your agent works even when AMP is unavailable:

\\\typescript let context; try { context = await amp.getContext({ userId: user.id, task: userQuery }); } catch (error) { console.warn('AMP unavailable:', error.code); context = { suggestedFraming: 'achievement', communicationStyle: 'conversational', complexity: 'break_into_steps', encouragement: 'moderate', confidence: 0.5 }; } // Continue with context regardless \\\


=== GUIDES ===

Integration Examples

Personal Assistant Agent

\\\`typescript import { AMP } from '@amp-protocol/client';

const amp = new AMP({ apiKey: process.env.AMP_API_KEY });

async function personalAssistant(userId: string, message: string) { const context = await amp.getContext({ userId, task: message, taskType: detectTaskType(message), });

const systemPrompt = \You are a personal assistant. Style: ${context.communicationStyle} Framing: ${context.suggestedFraming} Detail: ${context.complexity} Encouragement: ${context.encouragement}\;

const response = await llm.generate({ system: systemPrompt, user: message });

// Track outcome asynchronously trackOutcome(context.requestId, userId);

return response; } \\\`

Team Management Agent

\\\`typescript async function teamAgent(teamMembers: string[], task: string) { // Get context for each team member in parallel const contexts = await Promise.all( teamMembers.map(id => amp.getContext({ userId: id, task, taskType: 'team_task' }) ) );

// Personalise assignment message for each member return contexts.map((ctx, i) => ({ userId: teamMembers[i], message: buildAssignment(task, ctx), framing: ctx.suggestedFraming, })); } \\\`

Educational Tutor Agent

\\\typescript async function tutorAgent(studentId: string, topic: string) { const context = await amp.getContext({ userId: studentId, task: \learn ${topic}\`, taskType: 'learning', });

let lesson: string;

if (context.complexity === 'break_into_steps') { lesson = await generateProgressiveLessons(topic); } else if (context.complexity === 'hints_only') { lesson = await generateSocraticQuestions(topic); } else { lesson = await generateComprehensiveLesson(topic); }

if (context.encouragement === 'high') { lesson = addProgressTracking(lesson); }

return lesson; } \\\`

Customer Support Agent

\\\`python from amp_protocol import AMP

amp = AMP(api_key=os.getenv("AMP_API_KEY"))

async def support_agent(user_id: str, issue: str): context = await amp.get_context( user_id=user_id, task=f"resolve: {issue}", task_type="support", )

if context.communication_style == "brief_directive": response = generate_quick_fix(issue) elif context.communication_style == "detailed_explanatory": response = generate_walkthrough(issue) else: response = generate_standard_response(issue)

await amp.report_outcome( request_id=context.request_id, started=True, completed=True, )

return response \\\`


Best Practices

Context Usage

  • Always call getContext() before generating responses — This is the core integration point
  • Provide descriptive task strings — \"fix authentication bug in login form"\ is far better than \"help"\
  • Include taskType when known — Enables per-task-type personalisation
  • Use all returned fields — They work together as a coherent recommendation

Outcome Reporting

  • Report every interaction — Including negative outcomes (abandonments, non-starts)
  • Report in the background — Fire-and-forget pattern, do not block the user
  • Include optional fields — \timeToStart\, \flowState\, \satisfaction\ provide richer learning signals
  • Be honest — Report actual behaviour, not optimistic assumptions

Profile Management

  • Let AMP learn naturally — Avoid overriding profiles unless you have explicit user preferences
  • Use updateProfile() sparingly — For onboarding data or explicit user requests only
  • Monitor profile evolution — Verify that completion rates improve over time

Error Handling

  • Always implement fallbacks — Your agent should work even if AMP is offline
  • Use exponential backoff for retries — Respect \retryAfter\ headers
  • Log errors, don't expose them — Users should not see AMP-level errors

Performance

  • Call getContext() asynchronously — Do not block the request pipeline
  • Cache conservatively — TTL under 5 minutes to avoid stale recommendations
  • Use parallel calls — When personalising for multiple users simultaneously

Security

  • Store API keys in environment variables — Never in code or version control
  • Use separate keys per environment — dev, staging, production
  • Rotate keys every 90 days
  • Hash user identifiers — Do not send PII as userId

Testing & Debugging

Test Mode

Use test-mode API keys during development:

\\\bash AMP_API_KEY=amp_sk_test_1234567890abcdef \\\

Test mode provides:

  • Free unlimited requests
  • Isolated data sandbox
  • Profiles reset monthly
  • No billing impact

Sandbox Users

Create predictable test users with known profiles:

\\\`typescript // Set up a known profile for testing await amp.updateProfile({ userId: 'test_user_achiever', preferredFraming: 'achievement', communicationStyle: 'brief_directive', });

// Verify your agent adapts correctly const context = await amp.getContext({ userId: 'test_user_achiever', task: 'test task', });

assert(context.suggestedFraming === 'achievement'); \\\`

Unit Testing with Mocks

\\\`typescript jest.mock('@amp-protocol/client');

const mockGetContext = jest.fn().mockResolvedValue({ requestId: 'test_req', suggestedFraming: 'achievement', communicationStyle: 'brief_directive', complexity: 'break_into_steps', confidence: 0.8, });

AMP.prototype.getContext = mockGetContext;

test('adapts response based on AMP context', async () => { const response = await handleUserRequest('user_123', 'build login'); expect(mockGetContext).toHaveBeenCalledWith({ userId: 'user_123', task: 'build login', }); expect(response).toContain('Step 1'); }); \\\`

Testing All Framing Types

\\\typescript test.each([ ['achievement', 'Complete this'], ['learning', 'Explore how'], ['micro_task', 'Start by'], ['challenge', 'Can you'], ])('handles %s framing correctly', async (framing, expectedPhrase) => { mockGetContext.mockResolvedValue({ suggestedFraming: framing }); const response = await generateResponse('build feature'); expect(response).toContain(expectedPhrase); }); \\\

Debug Logging

\\\typescript const amp = new AMP({ apiKey: process.env.AMP_API_KEY, debug: true, // Logs all requests and responses }); \\\

Inspecting Recommendations

\\\`typescript const context = await amp.getContext({ userId: user.id, task });

console.log('AMP context:', { framing: context.suggestedFraming, style: context.communicationStyle, confidence: context.confidence, rationale: context.rationale, phase: context.metadata.profilePhase, }); \\\`

Common Issues

IssueCauseFix
Low confidence persistsNot enough interactions or poor task descriptionsProvide richer task strings, report all outcomes
Same recommendation every timeOutcome reporting missing or always positiveVerify reportOutcome() is called with accurate data
Unexpected recommendationsUser behaviour differs from assumptionsCheck the \rationale\ field to understand AMP's reasoning

Production Checklist

Pre-Launch

Credentials:

  • [ ] Switched from test to live API key (\amp_sk_live_\)
  • [ ] API key stored in environment variables or secrets manager
  • [ ] Key is not committed to version control
  • [ ] Key rotation schedule established (90-day cycle)

Error Handling:

  • [ ] Fallback behaviour implemented for AMP outages
  • [ ] Retry logic with exponential backoff in place
  • [ ] Errors logged to monitoring service
  • [ ] Graceful degradation tested end-to-end

Outcome Reporting:

  • [ ] reportOutcome() called for every interaction
  • [ ] Reporting runs in background (non-blocking)
  • [ ] Optional fields (timeToStart, flowState, satisfaction) included when available

Performance:

  • [ ] AMP adds < 50ms latency to responses
  • [ ] Appropriate request timeouts configured
  • [ ] Caching strategy in place (TTL < 5 minutes)
  • [ ] Load tested with expected user volume

Monitoring

\\\typescript const amp = new AMP({ apiKey: process.env.AMP_API_KEY, onRequest: (params) => { metrics.increment('amp.request'); }, onResponse: (context, duration) => { metrics.timing('amp.latency', duration); metrics.gauge('amp.confidence', context.confidence); }, onError: (error) => { metrics.increment('amp.error', { code: error.code }); logger.error('AMP error', error); } }); \\\

Gradual Rollout

Roll out AMP to a percentage of users first:

\\\`typescript const ROLLOUT_PERCENTAGE = 25;

async function handleRequest(userId: string, query: string) { const useAMP = hashId(userId) % 100 < ROLLOUT_PERCENTAGE;

if (useAMP) { const context = await amp.getContext({ userId, task: query }); return generateAdaptedResponse(query, context); } else { return generateDefaultResponse(query); } } \\\`

Post-Launch Metrics

Track weekly:

MetricWhat It Tells You
Completion RateAre users completing more tasks with AMP?
Time to StartAre users procrastinating less?
Flow State FrequencyAre users more engaged?
AMP ConfidenceAre profiles converging and stabilising?

Success threshold: A 20%+ increase in task completion rates within 30 days indicates effective integration.


=== SDK REFERENCE ===

TypeScript SDK

Installation

\\\bash npm install @amp-protocol/client \\\

Client Configuration

\\\`typescript import { AMP } from '@amp-protocol/client';

const amp = new AMP({ apiKey: process.env.AMP_API_KEY, baseUrl: 'https://api.amp-protocol.dev/v1', // default timeout: 5000, // request timeout in ms retries: 3, // auto-retry failed requests debug: false, // enable debug logging }); \\\`

Methods

getContext() — Get motivation context: \\\typescript const context = await amp.getContext({ userId: 'user_123', task: 'build a feature', complexity: 'medium', taskType: 'coding', metadata: { source: 'chat' }, }); \\\

reportOutcome() — Report interaction outcome: \\\typescript await amp.reportOutcome({ requestId: context.requestId, started: true, completed: true, timeToStart: 45, flowState: true, satisfaction: 0.9, }); \\\

updateProfile() — Override profile preferences: \\\typescript const profile = await amp.updateProfile({ userId: 'user_123', preferredFraming: 'achievement', communicationStyle: 'brief_directive', }); \\\

TypeScript Types

\\\typescript import type { GetContextParams, MotivationContext, OutcomeParams, MotivationProfile, UpdateProfileParams, FramingType, CommunicationStyle, ComplexityLevel, EncouragementLevel, } from '@amp-protocol/client'; \\\

Error Handling

\\\`typescript import { AMPError } from '@amp-protocol/client';

try { const context = await amp.getContext({ userId: user.id, task }); } catch (error) { if (error instanceof AMPError) { console.error(\AMP error: ${error.code} - ${error.message}\); console.error(\HTTP status: ${error.statusCode}\); } } \\\`

Event Listeners / Middleware

\\\`typescript amp.on('request', (params) => { console.log('AMP request:', params); });

amp.on('response', (context, durationMs) => { console.log(\AMP response in ${durationMs}ms, confidence: ${context.confidence}\); });

amp.on('error', (error) => { console.error('AMP error:', error.code); }); \\\`


Python SDK

Installation

\\\bash pip install amp-protocol \\\

Client Configuration

\\\`python from amp_protocol import AMP import os

amp = AMP( api_key=os.getenv("AMP_API_KEY"), base_url="https://api.amp-protocol.dev/v1", # default timeout=5.0, # request timeout in seconds max_retries=3, # auto-retry failed requests debug=False, # enable debug logging ) \\\`

Async Methods

get_context(): \\\python context = await amp.get_context( user_id="user_123", task="build a feature", complexity="medium", task_type="coding", metadata={"source": "chat"}, ) \\\

report_outcome(): \\\python await amp.report_outcome( request_id=context.request_id, started=True, completed=True, time_to_start=45, flow_state=True, satisfaction=0.9, ) \\\

update_profile(): \\\python profile = await amp.update_profile( user_id="user_123", preferred_framing="achievement", communication_style="brief_directive", ) \\\

Synchronous Client

\\\`python from amp_protocol import AMPSync

amp_sync = AMPSync(api_key=os.getenv("AMP_API_KEY"))

No async/await needed

context = amp_sync.get_context(user_id="user_123", task="test") amp_sync.report_outcome(request_id=context.request_id, started=True) \\\`

Type Hints

\\\`python from amp_protocol import ( AMP, MotivationContext, MotivationProfile, FramingType, CommunicationStyle, )

Fully typed with Pydantic models

context: MotivationContext = await amp.get_context( user_id="user_123", task="test" ) \\\`

Error Handling

\\\`python from amp_protocol.exceptions import ( AMPError, RateLimitError, UnauthorizedError, ValidationError, )

try: context = await amp.get_context(user_id=user_id, task=task) except RateLimitError as e: print(f"Rate limited. Retry after {e.retry_after}s") except UnauthorizedError: print("Invalid API key") except ValidationError as e: print(f"Invalid params: {e.message}") except AMPError as e: print(f"AMP error: {e.code} - {e.message}") \\\`


REST API

Base URL

\\\ https://api.amp-protocol.dev/v1 \\\

Authentication

Include your API key in the \Authorization\ header:

\\\ Authorization: Bearer amp_sk_live_your_key_here Content-Type: application/json \\\

Endpoints

POST /v1/context

Get motivation-aware context for a user interaction.

\\\bash curl -X POST https://api.amp-protocol.dev/v1/context \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "userId": "user_123", "task": "build a login page", "complexity": "medium", "taskType": "coding" }' \\\

Response: \\\json { "requestId": "req_abc123", "suggestedFraming": "micro_task", "communicationStyle": "brief_directive", "complexity": "break_into_steps", "encouragement": "moderate", "confidence": 0.87, "rationale": "User has 85% completion rate with step-by-step guidance", "metadata": { "profilePhase": "optimised", "interactionCount": 47, "explorationMode": false } } \\\

POST /v1/outcome

Report interaction outcome.

\\\bash curl -X POST https://api.amp-protocol.dev/v1/outcome \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "requestId": "req_abc123", "started": true, "completed": true, "timeToStart": 45, "flowState": true, "satisfaction": 0.9 }' \\\

Response: \\\json { "acknowledged": true, "profileUpdated": true } \\\

PUT /v1/profile/:userId

Update user profile preferences.

\\\bash curl -X PUT https://api.amp-protocol.dev/v1/profile/user_123 \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preferredFraming": "achievement", "communicationStyle": "brief_directive" }' \\\

Response: \\\json { "userId": "user_123", "preferredFraming": "achievement", "communicationStyle": "brief_directive", "complexityPreference": "break_into_steps", "encouragementLevel": "moderate", "totalInteractions": 47, "completionRate": 0.85, "confidence": 0.87 } \\\

Rate Limit Headers

All responses include rate limit information:

\\\ X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1642247400 \\\

Webhooks (Coming Soon)

Register webhook endpoints to receive real-time notifications when user profiles reach key milestones:

\\\json { "event": "profile.optimised", "userId": "user_123", "confidence": 0.92, "interactionCount": 25 } \\\

Error Response Format

All errors follow a consistent structure:

\\\json { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Too many requests. Please retry after 60 seconds.", "details": { "limit": 100, "window": "60s", "retryAfter": 42 }, "requestId": "req_abc123", "timestamp": "2024-01-15T10:30:00Z" } } \\\

Ready to Make Your AI Adapt?

Get Your API Key and Start Seeing Results in 24 Hours