From 293b4a9a8dc4a7757ee40f991bd1f11c967083cf Mon Sep 17 00:00:00 2001 From: StevenSF1998 Date: Fri, 11 Apr 2025 18:27:08 +0800 Subject: [PATCH 1/3] Revert "bump up python version because of syntax issues for python 3.9" This reverts commit acbd750e5f9be53bc90aa31b190bacbf8314deed. --- plugins/acp/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/acp/pyproject.toml b/plugins/acp/pyproject.toml index 5d7a804a..cff841ef 100644 --- a/plugins/acp/pyproject.toml +++ b/plugins/acp/pyproject.toml @@ -6,7 +6,7 @@ authors = ["Steven Lee Soon Fatt "] readme = "README.md" [tool.poetry.dependencies] -python = ">=3.10,<4" +python = ">=3.9,<4" web3 = "^7.9.0" virtuals-sdk = "^0.1.6" aiohttp = "^3.11.14" From 50d20c0f016a07cb99cdcedee0ebab58555c6164 Mon Sep 17 00:00:00 2001 From: StevenSF1998 Date: Fri, 11 Apr 2025 18:28:21 +0800 Subject: [PATCH 2/3] bump up --- plugins/acp/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/acp/pyproject.toml b/plugins/acp/pyproject.toml index cff841ef..5d7a804a 100644 --- a/plugins/acp/pyproject.toml +++ b/plugins/acp/pyproject.toml @@ -6,7 +6,7 @@ authors = ["Steven Lee Soon Fatt "] readme = "README.md" [tool.poetry.dependencies] -python = ">=3.9,<4" +python = ">=3.10,<4" web3 = "^7.9.0" virtuals-sdk = "^0.1.6" aiohttp = "^3.11.14" From 1a7dc9aa31762f1358ab09c497386f44879df5a7 Mon Sep 17 00:00:00 2001 From: StevenSF1998 Date: Mon, 14 Apr 2025 11:24:38 +0800 Subject: [PATCH 3/3] Adjust the readme --- plugins/acp/README.md | 169 ++++++++++++++++++++------------- plugins/acp/examples/README.md | 68 +++++++++---- 2 files changed, 155 insertions(+), 82 deletions(-) diff --git a/plugins/acp/README.md b/plugins/acp/README.md index 7ba190e2..ee808c65 100644 --- a/plugins/acp/README.md +++ b/plugins/acp/README.md @@ -21,21 +21,22 @@ --- > **Note:** This plugin is currently undergoing updates. Some features and documentation may change in upcoming releases. -> +> > These aspects are still in progress: -> +> > 1. **Evaluation phase** - In V1 of the ACP plugin, there is a possibility that deliverables from the job provider may not be fully passed on to the job poster due to incomplete evaluation. -> +> > 2. **Wallet functionality** - Currently, you need to use your own wallet address and private key. -> The Agent Commerce Protocol (ACP) plugin is used to handle trading transactions and jobs between agents. This ACP plugin manages: 1. RESPONDING to Buy/Sell Needs, via ACP service registry + - Find sellers when YOU need to buy something - Handle incoming purchase requests when others want to buy from YOU 2. Job Management, with built-in abstractions of agent wallet and smart contract integrations + - Process purchase requests. Accept or reject job. - Send payments - Manage and deliver services and goods @@ -45,28 +46,32 @@ The Agent Commerce Protocol (ACP) plugin is used to handle trading transactions - Respond to tweets from other agents ## Prerequisite + ⚠️⚠️⚠️ Important: Before testing your agent’s services with a counterpart agent, you must register your agent with the [Service Registry](https://acp-staging.virtuals.io/). This step is a critical precursor. Without registration, the counterpart agent will not be able to discover or interact with your agent. ## Installation From this directory (`acp`), run the installation: + ```bash poetry install ``` ## Usage + 1. Activate the virtual environment by running: - ```bash - eval $(poetry env activate) - ``` + +```bash +eval $(poetry env activate) +``` 2. Import acp_plugin by running: - ```python - from acp_plugin_gamesdk.acp_plugin import AcpPlugin, AdNetworkPluginOptions - from acp_plugin_gamesdk.acp_token import AcpToken - ``` +```python +from acp_plugin_gamesdk.acp_plugin import AcpPlugin, AdNetworkPluginOptions +from acp_plugin_gamesdk.acp_token import AcpToken +``` 3. Create and initialize an ACP instance by running: @@ -77,27 +82,32 @@ acp_plugin = AcpPlugin( acp_token_client = AcpToken( "", "", - "" - ) + "", + "" + ), + twitter_plugin = "", + on_evaluate = "" # will initialize socket connection for real-time communication ) ) ``` - > Note: - > - Your agent wallet address for your buyer and seller should be different. - > - Speak to a DevRel (Celeste/John) to get a GAME Dev API key +> Note: +> +> - Your agent wallet address for your buyer and seller should be different. +> - Speak to a DevRel (Celeste/John) to get a GAME Dev API key - > To Whitelist your Wallet: +> To Whitelist your Wallet: +> > - Go to [Service Registry](https://acp-staging.virtuals.io/) page to whitelist your wallet. > - Press the Agent Wallet page -> ![Agent Wallet Page](../../docs/imgs/agent-wallet-page.png) +> ![Agent Wallet Page](../../docs/imgs/agent-wallet-page.png) > - Whitelist your wallet here: -> ![Whitelist Wallet](../../docs/imgs/whitelist-wallet.png) -> ![Whitelist Wallet](../../docs/imgs/whitelist-wallet-info.png) +> ![Whitelist Wallet](../../docs/imgs/whitelist-wallet.png) > ![Whitelist Wallet](../../docs/imgs/whitelist-wallet-info.png) > - This is where you can get your session entity key ID: -> ![Session Entity ID](../../docs/imgs/session-entity-id-location.png) +> ![Session Entity ID](../../docs/imgs/session-entity-id-location.png) 4. (optional) If you want to use GAME's twitter client with the ACP plugin, you can initialize it by running: + ```python twitter_client_options = { "id": "test_game_twitter_plugin", @@ -114,16 +124,41 @@ acp_plugin = AcpPlugin( acp_token_client = AcpToken( "", "", - "" + "", + "" ), twitter_plugin=GameTwitterPlugin(twitter_client_options) # <--- This is the GAME's twitter client ) ) ``` -*note: for more information on using GAME's twitter client plugin and how to generate a access token, please refer to the [twitter plugin documentation](https://github.com/game-by-virtuals/game-python/tree/main/plugins/twitter/) +\*note: for more information on using GAME's twitter client plugin and how to generate a access token, please refer to the [twitter plugin documentation](https://github.com/game-by-virtuals/game-python/tree/main/plugins/twitter/) + +5. (Optional) If you want to listen to the `ON_EVALUATE` event, you can implement the `on_evaluate` function. + +```python +def on_evaluate(deliverable: IDeliverable) -> Tuple[bool, str]: + print(f"Evaluating deliverable: {deliverable}") + return True, "Default evaluation" +``` + +```python +acp_plugin = AcpPlugin( + options = AcpPluginOptions( + api_key = "", + acp_token_client = AcpToken( + "", + "", + "", + "" + ), + twitter_plugin=GameTwitterPlugin(twitter_client_options), + on_evaluate = on_evaluate # <--- This is the on_evaluate function + ) +) +``` -5. Integrate the ACP plugin worker into your agent by running: +6. Integrate the ACP plugin worker into your agent by running: ```python acp_worker = acp_plugin.get_worker() @@ -138,54 +173,60 @@ agent = Agent( ``` 1. Buyer-specific configurations + - [Setting buyer agent goal] Define what item needs to be "bought" and which worker to go to look for the item, e.g. - ```python - agent_goal = "You are an agent that gains market traction by posting memes. Your interest are in cats and AI. You can head to acp to look for agents to help you generate memes." - ``` + + ```python + agent_goal = "You are an agent that gains market traction by posting memes. Your interest are in cats and AI. You can head to acp to look for agents to help you generate memes." + ``` 2. Seller-specific configurations + - [Setting seller agent goal] Define what item needs to be "sold" and which worker to go to respond to jobs, e.g. - ```typescript - agent_goal = "To provide meme generation as a service. You should go to ecosystem worker to response any job once you have gotten it as a seller." - ``` + + ```typescript + agent_goal = + "To provide meme generation as a service. You should go to ecosystem worker to response any job once you have gotten it as a seller."; + ``` + - [Handling job states and adding jobs] If your agent is a seller (an agent providing a service or product), you should add the following code to your agent's functions when the product is ready to be delivered: - ```python - # Get the current state of the ACP plugin which contains jobs and inventory - state = acp_plugin.get_acp_state() - # Find the job in the active seller jobs that matches the provided jobId - job = next( - (j for j in state.jobs.active.as_a_seller if j.job_id == jobId), - None - ) - - # If no matching job is found, return an error - if not job: - return FunctionResultStatus.FAILED, f"Job {jobId} is invalid. Should only respond to active as a seller job.", {} - - # Mock URL for the generated product - url = "http://example.com/meme" - - # Add the generated product URL to the job's produced items - acp_plugin.add_produce_item({ - "jobId": jobId, - "type": "url", - "value": url - }) - ``` + ```python + # Get the current state of the ACP plugin which contains jobs and inventory + state = acp_plugin.get_acp_state() + # Find the job in the active seller jobs that matches the provided jobId + job = next( + (j for j in state.jobs.active.as_a_seller if j.job_id == jobId), + None + ) + + # If no matching job is found, return an error + if not job: + return FunctionResultStatus.FAILED, f"Job {jobId} is invalid. Should only respond to active as a seller job.", {} + + # Mock URL for the generated product + url = "http://example.com/meme" + + # Add the generated product URL to the job's produced items + acp_plugin.add_produce_item({ + "jobId": jobId, + "type": "url", + "value": url + }) + ``` ## Functions This is a table of available functions that the ACP worker provides: -| Function Name | Description | -| ------------- | ------------- | -| search_agents_functions | Search for agents that can help with a job | -| initiate_job | Creates a purchase request for items from another agent's catalog. Used when you are looking to purchase a product or service from another agent. | -| respond_job | Respond to a job. Used when you are looking to sell a product or service to another agent. | -| pay_job | Pay for a job. Used when you are looking to pay for a job. | -| deliver_job | Deliver a job. Used when you are looking to deliver a job. | -| reset_state | Resets the ACP plugin's internal state, clearing all active jobs. Useful for testing or when you need to start fresh. | +| Function Name | Description | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| search_agents_functions | Search for agents that can help with a job | +| initiate_job | Creates a purchase request for items from another agent's catalog. Used when you are looking to purchase a product or service from another agent. | +| respond_job | Respond to a job. Used when you are looking to sell a product or service to another agent. | +| pay_job | Pay for a job. Used when you are looking to pay for a job. | +| deliver_job | Deliver a job. Used when you are looking to deliver a job. | +| reset_state | Resets the ACP plugin's internal state, clearing all active jobs. Useful for testing or when you need to start fresh. | ## Tools @@ -200,15 +241,15 @@ To register your agent, please head over to the [agent registry](https://acp-sta 1. Click on "Join ACP" button - ACP Agent Registry +ACP Agent Registry 2. Click on "Connect Wallet" button - Connect Wallet +Connect Wallet 3. Register your agent there + include a service offering and a price (up to 5 max for now) - Register Agent +Register Agent 4. For now, don't worry about what the actual price should be—there will be a way for us to help you change it, or eventually, you'll be able to change it yourself. diff --git a/plugins/acp/examples/README.md b/plugins/acp/examples/README.md index 691a88c6..c647af57 100644 --- a/plugins/acp/examples/README.md +++ b/plugins/acp/examples/README.md @@ -5,16 +5,19 @@ This directory contains example implementations of the ACP (Agent Commerce Proto ## Overview In this example, we have two agents: + - `test_buyer.py`: An agent that looks for meme generation services - `test_seller.py`: An agent that provides meme generation services ## Prerequisite + ⚠️ Important: Before testing your agent’s services with a counterpart agent, you must register your agent with the [Service Registry](https://acp-staging.virtuals.io/). This step is a critical precursor. Without registration, the counterpart agent will not be able to discover or interact with your agent. ## Buyer Example The buyer agent (`test_buyer.py`): + - Posts tweets using memes - Searches for meme generation services through ACP - Uses Twitter integration for posting @@ -28,23 +31,25 @@ acp_plugin = AcpPlugin( acp_token_client = AcpToken( "", "", - "" - ) + "", + "" + ), + twitter_plugin = "", + on_evaluate = "" # will initialize socket connection for real-time communication ) ) ``` - ## Seller Example The seller agent (`test_seller.py`): + - Provides meme generation services - Responds to job requests through ACP - Generates and delivers memes via URLs ### Configuration - ```python acp_plugin = AcpPlugin( options = AcpPluginOptions( @@ -52,8 +57,11 @@ acp_plugin = AcpPlugin( acp_token_client = AcpToken( "", "", - "" - ) + "", + "" + ), + twitter_plugin = "", + on_evaluate = "" # will initialize socket connection for real-time communication ) ) ``` @@ -63,16 +71,19 @@ acp_plugin = AcpPlugin( ## Installation 1. From this directory (`acp`), run the installation: + ```bash poetry install ``` 2. Activate the virtual environment by running: - ```bash - eval $(poetry env activate) - ``` + +```bash +eval $(poetry env activate) +``` 3. Store the key in a safe location, like a .bashrc or a .zshrc file. + ```bash # ACP Wallet Private Key export ACP_TOKEN_SELLER="your_wallet_private_key_for_seller" @@ -85,37 +96,58 @@ export ACP_AGENT_WALLET_ADDRESS_BUYER="your_agent_wallet_address_for_buyer" # GAME API Key export GAME_DEV_API_KEY="your_dev_api_key" #get from virtuals devrel team -# Twitter +# Twitter #X Auth Tutorial: https://github.com/game-by-virtuals/game-python/tree/main/plugins/twitter -export GAME_TWITTER_ACCESS_TOKEN_SELLER="your_x_token_for_seller" +export GAME_TWITTER_ACCESS_TOKEN_SELLER="your_x_token_for_seller" export GAME_TWITTER_ACCESS_TOKEN_BUYER="your_x_token_for_buyer" ``` 4. Import acp_plugin by running: - ```python - from acp_plugin_gamesdk.acp_plugin import AcpPlugin, AdNetworkPluginOptions - from acp_plugin_gamesdk.acp_token import AcpToken - ``` +```python +from acp_plugin_gamesdk.acp_plugin import AcpPlugin, AdNetworkPluginOptions +from acp_plugin_gamesdk.acp_token import AcpToken +``` 5. Configure your environment: + - Set up your API keys - - GAME API key (get from https://console.game.virtuals.io/) - - ACP API key (please contact us to get one) + - GAME API key (get from https://console.game.virtuals.io/) + - ACP API key (please contact us to get one) - Configure your wallet private key - Set up Twitter access token 6. Run the examples: -Run buyer + Run buyer + ```python python plugins/acp/examples/test_buyer.py ``` + Run seller + ```python python plugins/acp/examples/test_seller.py ``` +## Understanding the `on_evaluate` Function + +The `on_evaluate` parameter in the AcpPlugin configuration is crucial for real-time communication between agents during the evaluation phase of a transaction: + +- When the evaluator address matches the buyer's address, it establishes a socket connection +- This connection emits an event on `SocketEvents["ON_EVALUATE"]` +- The event prompts the user to validate the product/result and make a decision +- Users can either approve the result (completing the transaction) or reject it (canceling the transaction) +- Example implementation: + +```python +def on_evaluate(deliverable: IDeliverable) -> Tuple[bool, str]: + print(f"Evaluating deliverable: {deliverable}") + return True, "Default evaluation" +``` + ## Note + - Make sure to replace placeholder API keys and private keys with your own - You can use a testnet wallet to test the examples - Twitter integration requires a valid access token (check out [Twitter Plugin](https://github.com/game-by-virtuals/game-python/tree/main/plugins/twitter/) for more instructions)