SfSkills Domains Docs GitHub

Home / agentforce / agentforce-custom-channel-dev

agentforce-custom-channel-dev

Use this skill when building custom channel integrations with the Agentforce Agent API or BYOC (Bring Your Own Channel) for CCaaS — covering session lifecycle management, webhook handling, externalSessionKey design, sequenceId sequencing, BYOC Interaction API integration, and conversation state management. NOT for standing up a standard channel (Embedded Service, Slack, Experience Cloud, Messaging) — use agentforce/agent-channel-deployment. NOT for writing the Apex actions the agent invokes — use agentforce/custom-agent-actions-apex.

Open the skill folder on GitHub


Agentforce Custom Channel Dev

This skill activates when a practitioner needs to integrate an external system, application, or communication platform with Agentforce using the Agent API session lifecycle or the BYOC (Bring Your Own Channel) for CCaaS pattern — covering webhook design, session state management, and the sequenceId/externalSessionKey protocol. Use this skill for programmatic, API-driven integrations, not standard channel deployments.


Before Starting

Gather this context before working on anything in this domain:


Core Concepts

Agent API Session Lifecycle

The Agentforce Agent API follows a strict three-phase lifecycle for every conversation:

1. Session Creation (POST)

POST https://api.salesforce.com/einstein/ai-agent/v1/agents/{agentId}/sessions

Request body:

{
  "externalSessionKey": "550e8400-e29b-41d4-a716-446655440000",
  "instanceConfig": {
    "endpoint": "https://your-org.salesforce.com"
  },
  "variables": [
    { "name": "Context.Channel", "type": "Text", "value": "custom-mobile-app" },
    { "name": "Context.EndUserLanguage", "type": "Text", "value": "en_US" }
  ],
  "bypassUser": false
}

The response returns a sessionId (Salesforce-generated UUID) distinct from the externalSessionKey. Store both — the sessionId is used for all subsequent calls; the externalSessionKey is your idempotency key.

2. Message Exchange (POST with sequenceId)

POST https://api.salesforce.com/einstein/ai-agent/v1/sessions/{sessionId}/messages

Request body:

{
  "message": {
    "sequenceId": 1,
    "type": "Text",
    "text": "Hello, I need help with my order"
  },
  "variables": []
}

The sequenceId must start at 1 and increment by 1 for each message in the session. The platform uses this to enforce message ordering — a duplicate or out-of-order sequenceId results in a 400 error.

3. Session Termination (DELETE)

DELETE https://api.salesforce.com/einstein/ai-agent/v1/sessions/{sessionId}

Always call DELETE when the conversation ends. Failing to do so leaves orphaned sessions that consume platform resources and may interfere with concurrent session limits.

externalSessionKey and Session Idempotency

The externalSessionKey is a caller-supplied UUID that acts as an idempotency key for session creation. If the same externalSessionKey is submitted to POST a second time (e.g., after a network timeout), the platform returns the existing session rather than creating a duplicate. This guarantees exactly-once session semantics even in unreliable network conditions.

Requirements:

BYOC for CCaaS — Interaction API vs. Raw Agent API

BYOC (Bring Your Own Channel) for CCaaS is a distinct integration pattern from the raw Agent API. It is designed for Contact Center as a Service (CCaaS) providers that want to route conversations through Salesforce Omni-Channel while leveraging Agentforce Service Agents.

The BYOC flow uses two APIs:

Establish Conversation API — initializes the conversation and creates or retrieves a MessagingEndUser record in Salesforce. This record represents the end user across Omni-Channel sessions and stores conversation history.

Interaction API — sends and receives messages between the external CCaaS platform and the Agentforce Service Agent through the Omni-Channel routing engine.

Key distinctions from raw Agent API:

DimensionRaw Agent APIBYOC for CCaaS
RoutingDirect to agent, no Omni-ChannelRoutes via Omni-Channel queue/agent assignment
End-user recordNo Salesforce record createdCreates/reuses MessagingEndUser object
Conversation historyExternal responsibilityStored in Salesforce Messaging Session
Auth scopeapi + refresh_token, offline_access + chatbot_api + sfap_apisame four + Omni-Channel permissions
Primary APIAgent API sessions endpointEstablish Conversation + Interaction API

Webhook Handling Patterns

When integrating an external system, the integration layer typically acts as a bidirectional webhook bridge:

Inbound (external system → Agentforce): The webhook receiver accepts messages from the external channel (IVR DTMF, mobile app text, CCaaS event), translates them to the Agent API message format, increments the sequenceId, and posts to the Agent API sessions endpoint.

Outbound (Agentforce → external system): The Agent API returns the agent's response synchronously in the POST /messages response body. Parse the messages array in the response to extract agent reply text and any structured data (rich content, handoff signals).

For BYOC CCaaS, Agentforce sends responses via the Interaction API push mechanism to a pre-registered webhook endpoint on the CCaaS side.


Common Patterns

Pattern 1: Direct Agent API Integration for Mobile or IVR

When to use: A mobile app, IVR system, or custom web surface needs to interact with an Agentforce agent programmatically without Omni-Channel routing.

How it works:

  1. Generate a UUIDv4 as externalSessionKey when the user starts a conversation.
  2. POST to the sessions endpoint with context variables (channel, language, user tier, etc.).
  3. Store the returned sessionId and initialize a sequenceId counter at 0.
  4. For each user message: increment sequenceId, POST to /messages, parse messages[].text from the response.
  5. On conversation end (user hangs up, session timeout, explicit close): DELETE the session.
  6. Handle 409 Conflict on session POST by re-using the existing sessionId returned in the conflict response body.

Why not the alternative: Using a custom Apex REST endpoint to "wrap" the agent is not supported — Apex endpoints cannot invoke the Agentforce reasoning engine or route through the Einstein Trust Layer.

Pattern 2: BYOC for CCaaS with Omni-Channel Routing

When to use: A CCaaS provider (e.g., Genesys, Amazon Connect, Five9) needs to surface an Agentforce Service Agent with full Omni-Channel routing, escalation to human agents, and Salesforce-side conversation history.

How it works:

  1. Register a BYOC channel in Salesforce Setup and obtain the channel endpoint credentials.
  2. Call the Establish Conversation API from the CCaaS platform when a new customer interaction begins. Salesforce creates or matches a MessagingEndUser record based on the provided identifier (phone number, email, or custom external ID).
  3. Route the conversation through the Interaction API — send customer messages as INBOUND_MESSAGE events, receive Agentforce responses as OUTBOUND_MESSAGE events pushed to the registered webhook.
  4. When the Agentforce agent determines escalation is needed, Omni-Channel handles the transfer to a human agent queue without additional API calls from the CCaaS side.
  5. On conversation close, send an END_CONVERSATION event via the Interaction API.

Why not the alternative: Using raw Agent API for CCaaS integrations loses Omni-Channel routing, supervisor monitoring, conversation history storage in Salesforce, and the escalation handoff mechanism — all of which are available only through the BYOC pathway.

Pattern 3: Stateful Conversation Context Design

When to use: The integration needs to carry user context (account tier, authenticated identity, preferred language) into the Agentforce session so the agent can personalize responses from the first message.

How it works:

Set context variables at session creation in the variables array. Common variables:

{
  "variables": [
    { "name": "Context.Channel", "type": "Text", "value": "mobile-ios" },
    { "name": "Context.EndUserLanguage", "type": "Text", "value": "fr_FR" },
    { "name": "Context.AuthenticatedUserId", "type": "Text", "value": "003xx000001GxyzAAC" }
  ]
}

Do not attempt to update these mid-session. If the user's language preference changes during the conversation, Context.EndUserLanguage is the only variable that can be updated — all others are locked for the session lifetime.

For state that genuinely changes during a conversation (e.g., items added to cart), manage that state externally (in your integration layer or a Salesforce custom object) and surface it to the agent via agent actions, not session variables.


Decision Guidance

SituationRecommended ApproachReason
Mobile app or custom web surface connecting directly to AgentforceRaw Agent API (POST/DELETE lifecycle)Direct, low-latency path; no Omni-Channel overhead needed
CCaaS platform needing Omni-Channel routing and human escalationBYOC for CCaaS (Establish Conversation + Interaction API)Omni-Channel routing, MessagingEndUser record, supervisor visibility, escalation
IVR system sending DTMF or voice-transcribed text to AgentforceRaw Agent API with context variable for channel typeIVR has no need for Omni-Channel queue; direct API is simpler
Need to inject user identity or account tier at start of sessionContext variables in session POST variables arrayOnly reliable injection point; variables are immutable post-creation
User language changes mid-conversationUpdate Context.EndUserLanguage onlyOnly this variable is mutable post-session-creation
Network timeout during session creationRetry POST with same externalSessionKey UUIDPlatform returns existing session on duplicate key — idempotent
Conversation ends (any reason)Always call DELETE on sessionPrevents orphaned sessions and resource leaks

Step-by-step instructions for an AI agent or practitioner building a custom Agentforce channel integration:

  1. Determine integration pattern — Confirm whether the use case requires raw Agent API (direct, no Omni-Channel) or BYOC for CCaaS (Omni-Channel routing, human escalation, MessagingEndUser records). These use different APIs, endpoints, and data models. Do not mix them.
  2. Configure Connected App and OAuth — Create or verify a Connected App (or External Client App) with all four OAuth scopes: api, refresh_token, offline_access, chatbot_api, and sfap_api. For BYOC CCaaS, also confirm Omni-Channel permissions. Retrieve the Agent ID from SELECT Id, DeveloperName FROM BotDefinition WHERE DeveloperName = 'YourAgent' or Setup > Agentforce Agents > Agent Detail.
  3. Design session management — Implement a UUIDv4 generator for externalSessionKey (one UUID per logical conversation). Initialize a per-session sequenceId counter starting at 0. Plan the session creation, message exchange, and DELETE lifecycle. Handle 409 Conflict on session POST by extracting sessionId from the conflict response.
  4. Define context variables — Determine which context variables to inject at session start (Context.Channel, Context.EndUserLanguage, authenticated user identifiers, account tier). Document that all variables except Context.EndUserLanguage are immutable for the session lifetime. Plan external state management for data that changes during a conversation.
  5. Implement webhook or event handling — For raw Agent API: parse the synchronous messages array in POST /messages responses. For BYOC CCaaS: register the inbound webhook endpoint, implement the Establish Conversation API call, and handle OUTBOUND_MESSAGE push events from the Interaction API.
  6. Implement graceful session termination — Ensure DELETE is called on session end in all code paths including timeouts, user drop-offs, errors, and explicit closes. Implement a session registry or TTL-based cleanup job for sessions that did not receive a DELETE.
  7. Test sequenceId sequencing and error handling — Validate that sequenceId increments correctly with no gaps. Test retry behavior using the same externalSessionKey. Verify that context variables injected at creation are present in early agent responses. Test DELETE and confirm the session is no longer accessible.

Review Checklist

Run through these before marking work in this area complete:


Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

  1. sequenceId gaps cause 400 errors — The platform enforces monotonically increasing sequenceIds with no gaps. If message 3 fails to send and the integration retries as message 4 without re-sending message 3, the session is corrupted and subsequent messages will be rejected. Always retry the failed message with the same sequenceId before incrementing.
  2. Context variables are immutable at session start (except EndUserLanguage) — Variables passed in the variables array at session creation cannot be changed for the lifetime of the session. The only exception is Context.EndUserLanguage, which can be updated via a subsequent API call. Attempting to "update" other variables mid-session has no effect — the original values are retained.
  3. externalSessionKey must be a UUID — The platform validates UUID format on session POST. Strings that look like session IDs (e.g., user-123-conversation-456, ISO timestamps, numeric IDs) are rejected with a 400 validation error. Use a proper UUIDv4 generator.
  4. BYOC CCaaS uses Interaction API, not raw Agent API — BYOC integrations do not call the Agent API sessions endpoint directly. They use the Establish Conversation API and Interaction API, which have different base paths, different event schemas, and different authentication requirements. Mixing the two APIs in a single integration causes session state errors and routing failures.
  5. Orphaned sessions from missing DELETE — Sessions not explicitly closed via DELETE remain active on the platform and count against concurrent session limits. In high-volume integrations (IVR, mobile), failure to call DELETE for dropped calls or timed-out sessions depletes the session pool. Implement a TTL-based background cleanup job.

Output Artifacts

ArtifactDescription
Session management implementationCode or pseudocode for session POST, message POST with sequenceId tracking, and session DELETE
externalSessionKey generatorUUIDv4 generation snippet with idempotency retry logic
Context variable injection planList of variables to inject at session creation with types and source data
Webhook endpoint designInbound/outbound message routing logic for raw Agent API or BYOC Interaction API
BYOC integration planEstablish Conversation API call sequence, MessagingEndUser record handling, Omni-Channel routing config
Session cleanup jobTTL-based or event-driven job to DELETE orphaned sessions


Official Sources Used

Dependencies

Package files