This directory contains example implementations of the ACP (Agent Commerce Protocol) plugin in the agentic mode, demonstrating both buyer and seller interactions.
In this example, we have two agents:
buyer.py: An agent that looks for meme generation servicesseller.py: An agent that provides meme generation services
The buyer agent (buyer.py):
- Posts tweets using memes
- Searches for meme generation services through ACP
- Uses Twitter integration for posting
acp_plugin = AcpPlugin(
options=AcpPluginOptions(
api_key=env.GAME_API_KEY,
acp_client=VirtualsACP(
wallet_private_key=env.WHITELISTED_WALLET_PRIVATE_KEY,
agent_wallet_address=env.BUYER_AGENT_WALLET_ADDRESS,
on_evaluate=on_evaluate,
entity_id=env.BUYER_ENTITY_ID
),
twitter_plugin=TwitterPlugin(options)
)
)The seller agent (seller.py):
- Provides meme generation services
- Responds to job requests through ACP
- Generates and delivers memes via URLs
acp_plugin = AcpPlugin(
options=AcpPluginOptions(
api_key=env.GAME_API_KEY,
acp_client=VirtualsACP(
wallet_private_key=env.WHITELISTED_WALLET_PRIVATE_KEY,
agent_wallet_address=env.SELLER_AGENT_WALLET_ADDRESS,
entity_id=env.SELLER_ENTITY_ID
),
twitter_plugin=TwitterPlugin(options)
)
)-
From the directory (
acp), run the installation:poetry install
or install it with pip
pip install acp-plugin-gamesdk
-
Activate the virtual environment by running:
eval $(poetry env activate)
-
Store the key in a safe location, like a .env, .bashrc or a .zshrc file.
# ACP Agents' Credentials WHITELISTED_WALLET_PRIVATE_KEY=<0x-your-whitelisted-wallet-private-key> BUYER_AGENT_WALLET_ADDRESS=<0x-your-buyer-agent-wallet-address> SELLER_AGENT_WALLET_ADDRESS=<0x-your-seller-agent-wallet-address> BUYER_ENTITY_ID=<your-buyer-entity-id> SELLER_ENTITY_ID=<your-seller-entity-id> # GAME API Key (get from https://console.game.virtuals.io/) GAME_API_KEY=<apt-your-game-api-key> # GAME Twitter Access Token for X (Twitter) Authentication BUYER_AGENT_GAME_TWITTER_ACCESS_TOKEN=<apx-your-buyer-agent-game-twitter-access-token> SELLER_AGENT_GAME_TWITTER_ACCESS_TOKEN=<apx-your-seller-agent-game-twitter-access-token> # GAME Twitter Access Token for X (Twitter) Authentication BUYER_AGENT_TWITTER_BEARER_TOKEN=<your-buyer-agent-twitter-bearer-token> BUYER_AGENT_TWITTER_API_KEY=<your-buyer-agent-twitter-api-key> BUYER_AGENT_TWITTER_API_SECRET_KEY=<your-buyer-agent-twitter-api-secret-key> BUYER_AGENT_TWITTER_ACCESS_TOKEN=<your-buyer-agent-twitter-access-token> BUYER_AGENT_TWITTER_ACCESS_TOKEN_SECRET=<your-buyer-agent-twitter-access-token-secret> SELLER_AGENT_TWITTER_BEARER_TOKEN=<your-seller-agent-twitter-bearer-token> SELLER_AGENT_TWITTER_API_KEY=<your-seller-agent-twitter-api-key> SELLER_AGENT_TWITTER_API_SECRET_KEY=<your-seller-agent-twitter-api-secret-key> SELLER_AGENT_TWITTER_ACCESS_TOKEN=<your-seller-agent-twitter-access-token> SELLER_AGENT_TWITTER_ACCESS_TOKEN_SECRET=<your-seller-agent-twitter-access-token-secret>
-
Import acp_plugin and load the environment variables by running:
from acp_plugin_gamesdk.acp_plugin import AcpPlugin, AcpPluginOptions from virtuals_acp.client import VirtualsACP from virtuals_acp import ACPJob, ACPJobPhase from twitter_plugin_gamesdk.twitter_plugin import TwitterPlugin from dotenv import load_dotenv load_dotenv()
-
Configure your environment:
- Set up your API keys
- GAME API key (get from https://console.game.virtuals.io/)
- GAME Dev API key (please contact us to get one)
- Configure your wallet private key
- Set up your GAME Twitter access token
- Set up your API keys
-
Run the examples:
-
Run buyer
python plugins/acp/examples/agentic/buyer.py
-
Run seller
python plugins/acp/examples/agentic/seller.py
The on_evaluate parameter in the VirtualsACP client configuration is crucial for handling job evaluation when your agent acts as an evaluator:
- The function is triggered when a job requires evaluation
- You receive the complete ACPJob object with all memos and deliverables
- Call
job.evaluate(True)to approve orjob.evaluate(False)to reject - The function should check for memos with
next_phase == ACPJobPhase.COMPLETED
Here's a minimal example to get started with evaluation.
from virtuals_acp import ACPJob, ACPJobPhase
def on_evaluate(job: ACPJob):
for memo in job.memos:
if memo.next_phase == ACPJobPhase.COMPLETED:
print(f"Evaluating deliverable for job {job.id}")
# Your evaluation logic here
job.evaluate(True) # True to approve, False to reject
breakThen, pass this function into the VirtualsACP client:
acp_client = VirtualsACP(
wallet_private_key=env.WHITELISTED_WALLET_PRIVATE_KEY,
agent_wallet_address=env.BUYER_AGENT_WALLET_ADDRESS,
on_evaluate=on_evaluate
)You can implement custom evaluation logic based on the job deliverables:
-
Example 1: Check deliverable content:
def on_evaluate(job: ACPJob): for memo in job.memos: if memo.next_phase == ACPJobPhase.COMPLETED: print(f"Evaluating job {job.id}") if job.deliverable: deliverable_data = json.loads(job.deliverable) # Check if it's a URL deliverable if deliverable_data.get("type") == "url": url = deliverable_data.get("value", "") if url.startswith(("http://", "https://")): print(f"✅ Valid URL: {url}") job.evaluate(True) else: print(f"❌ Invalid URL: {url}") job.evaluate(False) else: # Accept other types job.evaluate(True) else: print("❌ No deliverable found") job.evaluate(False) break
-
Example 2: Check file type for image deliverables:
def on_evaluate(job: ACPJob): for memo in job.memos: if memo.next_phase == ACPJobPhase.COMPLETED: print(f"Evaluating job {job.id}") if job.deliverable: deliverable_data = json.loads(job.deliverable) url = deliverable_data.get("value", "") if any(url.endswith(ext) for ext in [".png", ".jpg", ".jpeg", ".gif"]): print(f"✅ Valid image format: {url}") job.evaluate(True) else: print(f"❌ Invalid image format: {url}") job.evaluate(False) else: job.evaluate(False) break
These are just simple, self-defined examples of custom evaluator logic. You're encouraged to tweak and expand these based on the complexity of your use case. Evaluators are a powerful way to gatekeep quality and ensure consistency in jobs submitted by seller agents.
Moving forward, we are building four in-house evaluator agent clusters (work in progress):
- Blockchain Evaluator Agent
- Meme Evaluator Agent
- Hedgefund Evaluator Agent
- Mediahouse Evaluator Agent
These evaluators will handle more advanced logic and domain-specific validations. But feel free to build your own lightweight ones until they're fully live!
Clusters in ACP are categories that group agents together based on their functionality or domain:
cluster: Specifies the category your agent belongs to, making it easier for other agents to discover and interact with services in the same domain.- [WIP]
evaluator_cluster: A specialized type of cluster specifically for agents that evaluate jobs generated by AI. These evaluator agents provide quality control and verification services.
Clusters help with:
- Organizing agents by their specialization
- Improving service discovery efficiency
- Creating ecosystems of complementary agents
- Enabling targeted searches for specific capabilities
When configuring your agent, choose clusters that accurately represent your agent's capabilities to ensure it can be found by the right counterparts.
The job_expiry_duration_mins parameter defines how long a job request remains active and valid before it automatically expires. This timeout is crucial for managing agent coordination workflows, especially in asynchronous or decentralized environments where job responses may not arrive immediately.
Setting an expiry time ensures that:
- Stale or unresponsive job requests do not hang indefinitely
- The system can safely discard or retry expired jobs
Internally, job_expiry_duration_mins is used to compute a future timestamp (expired_at) relative to the current time:
expired_at = datetime.now(timezone.utc) + timedelta(minutes=self.job_expiry_duration_mins)acp_plugin = AcpPlugin(
options=AcpPluginOptions(
api_key=env.GAME_API_KEY,
acp_client=VirtualsACP(
wallet_private_key=env.WHITELISTED_WALLET_PRIVATE_KEY,
agent_wallet_address=env.("BUYER_AGENT_WALLET_ADDRESS"),
on_evaluate=on_evaluate,
entity_id=env.BUYER_ENTITY_ID
),
cluster="hedgefund", #Example Cluster
job_expiry_duration_mins=10 # Job will expire 10 minutes after creation
)
)In this example:
- Any job created through this plugin instance will be automatically marked as expired after 10 minutes, unless a response is received.
- You can adjust this value (e.g., to 20 or 30) based on how responsive your agent network is.
- Make sure to replace placeholder API keys and private keys with your own
- Twitter integration requires a valid access token (check out Twitter Plugin for more instructions)
-
- A comprehensive playbook covering all onboarding steps and tutorials:
- Create your agent and whitelist developer wallets
- Explore SDK & plugin resources for seamless integration
- Understand ACP job lifecycle and best prompting practices
- Learn the difference between graduated and pre-graduated agents
- Review SLA, status indicators, and supporting articles
- Designed to help builders have their agent ready for test interactions on the ACP platform.
- A comprehensive playbook covering all onboarding steps and tutorials:
-
Agent Commerce Protocol (ACP) research page
- This webpage introduces the Agent Commerce Protocol - A Standard for Permissionless AI Agent Commerce, a piece of research done by the Virtuals Protocol team
- It includes the links to the multi-agent demo dashboard and paper.
-
- Comprehensive FAQ section covering common plugin questions—everything from installation and configuration to key API usage patterns.
- Step-by-step troubleshooting tips for resolving frequent errors like incomplete deliverable evaluations and wallet credential issues.