For AI agents and developers: machine-readable getting-started guide and automated Salesforce org setup (/llms.txt).

Agent API - Headless Communication

Agent API - Headless Communication

Interact with your deployed Agentforce agents programmatically using REST APIs. Perfect for building custom integrations, testing workflows, or automating agent interactions.

API Usage Guide

Follow these steps to interact with your agent programmatically:

Step 0: Get OAuth Access Token

First, get an OAuth access token using your credentials. Copy the access_token from the response.

1
2
3
4
5
curl -X POST "https://myorg.my.salesforce.com/services/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

Response example:

1
2
3
4
5
6
7
8
{
  "access_token": "00D5e0000...",
  "instance_url": "https://your-org.my.salesforce.com",
  "id": "https://login.salesforce.com/id/...",
  "token_type": "Bearer",
  "issued_at": "1234567890",
  "signature": "..."
}

Step 1: Start Agent Session

Start a new agent session. Save the sessionId from the response.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
curl -X POST "https://api.salesforce.com/einstein/ai-agent/v1/agents/YOUR_AGENT_ID/sessions" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "externalSessionKey": "session_1234567890",
    "instanceConfig": {
      "endpoint": "https://myorg.my.salesforce.com"
    },
    "tz": "America/Los_Angeles",
    "variables": [{
      "name": "$Context.EndUserLanguage",
      "type": "Text",
      "value": "en_US"
    }],
    "bypassUser": true
  }'

Key parameters:

  • externalSessionKey: A unique identifier for this session (use timestamps or UUIDs)
  • instanceConfig.endpoint: Your Salesforce instance URL
  • tz: Timezone for the session
  • variables: Context variables for the agent
  • bypassUser: Set to true for headless API access

Response example:

1
2
3
4
5
{
  "sessionId": "0Xx5e0000...",
  "createdDate": "2024-01-01T00:00:00.000Z",
  "status": "ACTIVE"
}

Step 2: Send Message to Agent

Send a message to the agent. Increment sequenceId for each new message (1, 2, 3, ...).

1
2
3
4
5
6
7
8
9
10
curl -X POST "https://api.salesforce.com/einstein/ai-agent/v1/sessions/YOUR_SESSION_ID/messages" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": {
      "sequenceId": 1,
      "type": "Text",
      "text": "Hello! Can you help me?"
    }
  }'

Important: Track the sequenceId yourself - it must increment with each message in the session.

Response example:

1
2
3
4
5
6
7
8
9
10
{
  "messages": [
    {
      "sequenceId": 1,
      "type": "Text",
      "text": "Hello! I'm here to help. What can I assist you with today?",
      "role": "Agent"
    }
  ]
}

Step 3: End Agent Session

Close the session when done to free up resources.

1
2
3
curl -X DELETE "https://api.salesforce.com/einstein/ai-agent/v1/sessions/YOUR_SESSION_ID" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-session-end-reason: UserRequest"

Response: Returns HTTP 200 with a SessionEnded message.

Note: The x-session-end-reason header is required. Valid values: UserRequest, Transfer.

Streaming Responses

For real-time streaming responses, add streaming capabilities to your session:

1
2
3
4
5
6
{
  "featureSupport": "Streaming",
  "streamingCapabilities": {
    "chunkTypes": ["Text"]
  }
}

When streaming is enabled, responses will be sent as Server-Sent Events (SSE).

Error Handling

Common error responses:

Status CodeDescriptionSolution
401UnauthorizedOAuth token expired - get a new one
404Not FoundCheck agent ID or session ID
429Too Many RequestsRate limit exceeded - slow down requests
500Internal Server ErrorSalesforce server issue - retry with backoff

Rate Limits

  • Sessions per hour: 1000 per org
  • Messages per session: 100
  • Concurrent sessions: 50 per org

SDK Examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
const axios = require("axios");

const client = new AgentAPIClient(
  "https://myorg.my.salesforce.com",
  "YOUR_CLIENT_ID",
  "YOUR_CLIENT_SECRET"
);

class AgentAPIClient {
  constructor(instanceUrl, clientId, clientSecret) {
    this.instanceUrl = instanceUrl;
    this.clientId = clientId;
    this.clientSecret = clientSecret;
    this.baseUrl = "https://api.salesforce.com/einstein/ai-agent/v1";
  }

  async getAccessToken() {
    const response = await axios.post(
      `${this.instanceUrl}/services/oauth2/token`,
      new URLSearchParams({
        grant_type: "client_credentials",
        client_id: this.clientId,
        client_secret: this.clientSecret,
      }),
      { headers: { "Content-Type": "application/x-www-form-urlencoded" } }
    );
    return response.data.access_token;
  }

  async startSession(agentId, accessToken) {
    const response = await axios.post(
      `${this.baseUrl}/agents/${agentId}/sessions`,
      {
        externalSessionKey: `session_${Date.now()}`,
        instanceConfig: { endpoint: this.instanceUrl },
        tz: "America/Los_Angeles",
        bypassUser: true,
      },
      { headers: { Authorization: `Bearer ${accessToken}` } }
    );
    return response.data.sessionId;
  }

  async sendMessage(sessionId, text, sequenceId, accessToken) {
    const response = await axios.post(
      `${this.baseUrl}/sessions/${sessionId}/messages`,
      {
        message: {
          sequenceId,
          type: "Text",
          text,
        },
      },
      { headers: { Authorization: `Bearer ${accessToken}` } }
    );
    return response.data;
  }

  async endSession(sessionId, accessToken) {
    await axios.delete(`${this.baseUrl}/sessions/${sessionId}`, {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "x-session-end-reason": "UserRequest",
      },
    });
  }
}

// Usage
(async () => {
  const token = await client.getAccessToken();
  const sessionId = await client.startSession("YOUR_AGENT_ID", token);
  const response = await client.sendMessage(sessionId, "Hello!", 1, token);
  console.log(response);
  await client.endSession(sessionId, token);
})();

Tips

  • Token expiration: OAuth tokens expire after ~2 hours - implement token refresh logic
  • Session management: Always end sessions when done to avoid hitting Salesforce limits
  • Sequence tracking: Maintain sequence IDs on your side - they must increment sequentially
  • Error handling: Implement retry logic with exponential backoff for transient errors
  • Rate limiting: Respect rate limits and implement proper throttling

Additional Resources