A Pong game where two Salesforce Agentforce AI agents play against each other. Each rally is a real API call — one agent sends a message, the other responds, and the ball animates across the table between turns.
Built as a demo by Biztory.
- On game start, the server opens two concurrent Agentforce agent sessions via the Einstein AI Agent API.
- Player 1 serves with the word
PING. - On each rally, the current agent receives the previous agent's response as its prompt and replies.
- The ball animates across the table while the API call is in flight; the response text is shown on the table and in each agent's terminal.
- After the configured number of rallies the sessions are closed.
The Node.js backend handles all Salesforce API communication (OAuth token caching, session lifecycle, message dispatch). The frontend is a single static HTML file served by the same Express server.
- Node.js 18+
- A Salesforce org with Agentforce enabled
- Two deployed Agentforce agents (one per player)
- A Connected App in Salesforce configured for OAuth 2.0 Client Credentials flow
- A local TLS certificate for HTTPS (e.g. generated with mkcert)
git clone <repo-url>
cd PONGFORCE
npm installThe server requires HTTPS (Agentforce SSE requires a secure context).
mkcert a2a.pongforce.demoThis produces a2a.pongforce.demo-key.pem and a2a.pongforce.demo.pem in the current directory.
Add a hosts entry so the domain resolves locally:
127.0.0.1 a2a.pongforce.demo
Copy the example file and fill in your values:
cp .env.example .env| Variable | Description |
|---|---|
SF_DOMAIN |
Your Salesforce org URL, e.g. https://yourorg.my.salesforce.com |
CLIENT_ID |
Connected App consumer key |
CLIENT_SECRET |
Connected App consumer secret |
AGENT_API |
Einstein AI Agent API base URL (usually https://api.salesforce.com/einstein/ai-agent/v1) |
PLAYER1_ID |
Agent ID for Player 1 (Agent Blue) |
PLAYER2_ID |
Agent ID for Player 2 (Agent Red) |
PORT |
HTTPS port (default: 443) |
DEMO_URL |
Public base URL, e.g. https://a2a.pongforce.demo |
SSL_KEY_PATH |
Path to your TLS private key file |
SSL_CERT_PATH |
Path to your TLS certificate file |
sudo node server.js
sudois required to bind to port 443. Alternatively, setPORTto an unprivileged port (e.g.3000) and updateDEMO_URLaccordingly — nosudoneeded in that case.
Navigate to https://a2a.pongforce.demo (or whichever DEMO_URL you configured).
- Set Max rallies — the number of back-and-forth exchanges before the game ends.
- Click Start Game.
- Watch the agents play. Each agent's responses appear in its terminal panel below the table.
- Click Stop at any time to end the game early.
PONGFORCE/
├── server.js # Express/HTTPS server, Salesforce API proxy
├── public/
│ └── index.html # Single-page frontend (game UI + client logic)
├── .env # Local credentials (git-ignored)
├── .env.example # Environment variable template
├── .gitignore
└── package.json
| Method | Path | Description |
|---|---|---|
GET |
/api/config |
Returns agent IDs and API base URL for the frontend |
POST |
/api/session |
Opens an Agentforce agent session |
POST |
/api/message |
Sends a message to an agent session |
DELETE |
/api/session/:sessionId |
Closes an agent session |
- Salesforce credentials (
CLIENT_ID,CLIENT_SECRET) are kept server-side only and never sent to the browser. .envand*.pemfiles are git-ignored.- The
/api/configendpoint exposes only non-secret values (agent IDs and API base URL). - OAuth tokens are cached in memory for 25 minutes and refreshed automatically.

