Skip to main content
The Runflow Context is a global singleton that manages execution information and user identification. It allows you to identify once and all agents/workflows automatically use this context.

Why Identify Matters

When you call identify(), you’re telling Runflow who is interacting with your agent. This single call connects three critical systems:
  • Memory — conversation history is stored and retrieved by this identifier. Same identifier = same conversation history.
  • Traces — all execution traces are linked to this user, so you can search and filter by user in the dashboard.
  • Metrics — business events emitted with track() are associated with this user.
Without identify(), your agent still works, but memory won’t persist correctly between sessions and your dashboard data won’t be linked to specific users.
import { identify } from '@runflow-ai/sdk/observability';

// Always call identify BEFORE agent.process()
identify(userPhone);

const result = await agent.process({ message, sessionId });

Basic Usage

import { Agent, openai } from '@runflow-ai/sdk';
import { identify } from '@runflow-ai/sdk/observability';

// Identify user by phone (WhatsApp)
identify('+5511999999999');

// Agent automatically uses the context
const agent = new Agent({
  name: 'WhatsApp Bot',
  instructions: 'You are a helpful assistant.',
  model: openai('gpt-4o'),
  memory: {
    maxTurns: 10,
  },
});

// Memory is automatically bound to the phone number
await agent.process({
  message: 'Hello!',
});

Smart Identification (Auto-Detection)

New in v2.1: The identify() function now auto-detects entity type from value format:
import { identify } from '@runflow-ai/sdk/observability';

// Auto-detect email
identify('user@example.com');
// → type: 'email', value: 'user@example.com'

// Auto-detect phone (international)
identify('+5511999999999');
// → type: 'phone', value: '+5511999999999'

// Auto-detect phone (local with formatting)
identify('(11) 99999-9999');
// → type: 'phone', value: '(11) 99999-9999'

// Auto-detect UUID
identify('550e8400-e29b-41d4-a716-446655440000');
// → type: 'uuid'

// Auto-detect URL
identify('https://example.com');
// → type: 'url'
Supported patterns:
  • Email: Standard RFC 5322 format
  • Phone: E.164 format (with/without +, with/without formatting)
  • UUID: Standard UUID v1-v5
  • URL: With or without protocol
  • Fallback: Generic id type for custom identifiers

Explicit Identification

For custom entity types or when auto-detection is not desired:
import { identify } from '@runflow-ai/sdk/observability';

// HubSpot Contact
identify({
  type: 'hubspot_contact',
  value: 'contact_123',
  userId: 'user@example.com',
});

// Order/Ticket
identify({
  type: 'order',
  value: 'ORDER-456',
  userId: 'customer_789',
});

// Custom threadId override
identify({
  type: 'document',
  value: 'doc_456',
  threadId: 'custom_thread_123',
});

Common Patterns

WhatsApp / Phone Integration

The phone number is the natural identifier. Memory persists across all conversations with the same number:
identify('+5511999999999');

Email-Based

For web apps or email integrations:
identify('user@example.com');

Multi-Conversation

When the same user can have multiple independent conversations (e.g., different support tickets):
identify({
  type: 'session',
  value: `${userEmail}:${conversationId}`,
});

Integration Webhooks

Parse the identifier from the webhook payload:
export async function main(input: any) {
  // Extract identifier from whatever your integration sends
  const userId = input.email || input.phone || input.userId;

  identify(userId);

  const result = await agent.process({ message: input.message, sessionId: input.sessionId });
  return { message: result.message };
}

Backward Compatibility

The old Runflow.identify() API still works but is not recommended. Prefer the direct import:
import { identify } from '@runflow-ai/sdk/observability';

identify('user@example.com');

State Management

import { Runflow } from '@runflow-ai/sdk/core';

// Get complete state
const state = Runflow.getState();

// Get specific value
const threadId = Runflow.get('threadId');
const entityType = Runflow.get('entityType');

// Set custom state (advanced)
Runflow.setState({
  entityType: 'custom',
  entityValue: 'xyz',
  threadId: 'my_custom_thread_123',
  userId: 'user_123',
  metadata: { custom: 'data' },
});

// Clear state (useful for testing)
Runflow.clearState();

Next Steps

Best Practices

Identify patterns and more tips

Memory

Learn about memory management

Observability

Track execution with observability

Quick Start

See identify in action