Skip to Content

Fetch.ai SDK Guide: Search Agent

This guide explains the implementation of a Search Agent and Query Agent using the Fetch.ai SDK. These Agents work together to handle user queries, search the Fetch.ai network for relevant Agents, and return results.

Below, we outline the Search Function and the Complete Agent Implementation in details.

Installation

Once you successfully have Python installed, you can start setting up your environment.

Create a new folder; call it fetchai-search-agent:

mkdir fetchai-search-agent && cd fetchai-search-agent

Then, install the required libraries:

pip install uagents fetchai openai

Search Function

The Search Function is the core of the Search Agent. It interacts with the Fetch.ai network to find Agents matching a specific query and sends them a message.

Here’s how it works:

Functionalities

  • Search the Fetch.ai Network: The fetch.ai(query) method searches for Agents that match the user’s query.

  • Set Sender Identity: Each message is sent using a unique sender identity generated by Identity.from_seed.

  • Dynamic Payload: Uses OpenAI’s GPT to generate payload based on the query.

  • Send Messages: For every matching Agent, a payload is constructed and sent using the send_message_to_agent function.

from fetchai import fetch from fetchai.crypto import Identity from fetchai.communication import send_message_to_agent from uuid import uuid4 def search(query): # Search for agents matching the query available_ais = fetch.ai(query) # Create sender identity for communication sender_identity = Identity.from_seed("search_sender_identity", 0) for ai in available_ais.get('ais'): # Iterate through discovered agents prompt = f""" you will take the following information: query={query}. You must return a results according to the query""" completion = client.chat.completions.create( model="gpt-4o", messages=[ {"role": "user", "content": prompt} ] ) payload = { "Response": completion.choices[0].message.content } other_addr = ai.get("address", "") # Get agent's address print(f"Sending a message to an AI agent at address: {other_addr}") # Send the payload to the discovered agent send_message_to_agent( sender=sender_identity, target=other_addr, payload=payload, session=uuid4(), ) return {"status": "Agent searched"}

Complete Agent Implementation

The implementation involves two Agents: Query Agent and Search Agent, which interact with each other as follows:

Query Agent

  • It sends the user’s query to the Search Agent on startup.

  • it then waits for a response from the Search Agent.

    query_agent = Agent(name="query_agent", seed="query_agent recovery phrase")

Search Agent

-Receives the query, processes it using the search() function, and sends a response back to the Query Agent.

search_agent = Agent(name="search_agent", seed="search_agent recovery phrase")

Overall script

fetchai-search-agent.py
from fetchai import fetch from fetchai.crypto import Identity from fetchai.communication import ( send_message_to_agent ) from openai import OpenAI client = OpenAI() from uuid import uuid4 from uagents import Agent, Bureau, Context, Model class Query(Model): message: str class Response(Model): status: str def search(query): available_ais = fetch.ai(query) sender_identity = Identity.from_seed("whatever i want this to be, but i am searching", 0) print(f"[results] available ais : {available_ais} ") for ai in available_ais.get('ais'): prompt = f""" you will take the following information: query={query}. You must return a results according to the query""" completion = client.chat.completions.create( model="gpt-4o", messages=[ {"role": "user", "content": prompt} ] ) payload = { "Response": completion.choices[0].message.content } other_addr = ai.get("address", "") print(f"[INFO] Sending message to AI at address: {other_addr}") send_message_to_agent( sender=sender_identity, target=ai.get("address", ""), payload=payload, session=uuid4() ) return {"status": "Agent searched"} query_agent = Agent(name="query_agent", seed="query_agent recovery phrase") search_agent = Agent(name="search_agent", seed="search_agent recovery phrase") user_query = input("Enter your query: ") @query_agent.on_event("startup") async def send_message(ctx: Context): ctx.logger.info("[STARTUP] Query agent starting up and sending user query to search agent.") await ctx.send(search_agent.address, Query(message=user_query)) @search_agent.on_message(model=Query) async def sigmar_message_handler(ctx: Context, sender: str, msg: Query): ctx.logger.info(f"[RECEIVED] Query received from {sender}. Message: '{msg.message}'") results = search(msg.message) ctx.logger.info("[PROCESSING] Searching completed. Sending response back to the query agent.") await ctx.send(query_agent.address, Response(status=results["status"])) @query_agent.on_message(model=Response) async def slaanesh_message_handler(ctx: Context, sender: str, msg: Response): ctx.logger.info(f"[RECEIVED] Response received from search agent {sender}. Status: '{msg.status}'") bureau = Bureau() bureau.add(query_agent) bureau.add(search_agent) if __name__ == "__main__": print("[INFO] Starting Bureau with Query Agent and Search Agent...") bureau.run()

Running the Agent

We run fetchai-search-agent.py with the following commands:

python fetchai-search-agent.py

Expected output

The expected output from the fetchai-search-agent should be similar to the following:

Enter your query: Buy me a pair of shoes [INFO] Starting Bureau with Query Agent and Search Agent... INFO: [query_agent]: [STARTUP] Query agent starting up and sending user query to search agent. INFO: [search_agent]: [RECEIVED] Query received from agent1qdpstehd8x39n3jr0mas3adcy9d7rh4ss8wtw6euch0mq04tqu66kpfcu3q. Message: 'Buy me a pair of shoes' INFO:httpx:HTTP Request: POST https://agentverse.ai/v1/search/agents "HTTP/1.1 200 OK" [results] available ais : { "ais": [ { "address": "agent1qw7802t7qf98kg775k7f5v3f9h864c72eja2r94pumxnvyx3492xyzu8fmg", "name": "My AI's Name", "readme": "\n<description>Used for getting the nike shoes</description>\n<use_cases>\n <use_case>Used to get the nike shoes</use_case>\n</use_cases>\n<payload_requirements>\n<description>nike ai shoess</description>\n<payload>\n <requirement>\n <parameter>question</parameter>\n <description>to gwt the nike shoese</description>\n </requirement>\n</payload>\n</payload_requirements>\n", "protocols": [ { "name": "", "version": "", "digest": "proto:a03398ea81d7aaaf67e72940937676eae0d019f8e1d8b5efbadfef9fd2e98bb2" } ],... },... ] } INFO:httpx:HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" [INFO] Sending message to AI at address: agent1qv5jr3ylluy45hzwftgctt0hnaa75h2m0ehflxdw8rz3720pjmaegy2447r {"version":1,"sender":"agent1qdtxzn2e0dg8y2v5y53p7frplt4w6wq36rfapv38g8x9ukgpc28fgfqnjug","target":"agent1qv5jr3ylluy45hzwftgctt0hnaa75h2m0ehflxdw8rz3720pjmaegy2447r","session":"924e26cb-bae2-4442-95a6-02292125c4f4","schema_digest":"model:708d789bb90924328daa69a47f7a8f3483980f16a1142c24b12972a2e4174bc6","protocol_digest":"proto:a03398ea81d7aaaf67e72940937676eae0d019f8e1d8b5efbadfef9fd2e98bb2","payload":"eyJSZXNwb25zZSI6IkNlcnRhaW5seSEgQmFzZWQgb24geW91ciBxdWVyeSB0byBcIkJ1eSBtZSBhIHBhaXIgb2Ygc2hvZXMsXCIgaGVyZSBhcmUgc29tZSBnZW5lcmFsIHN0ZXBzIG9yIHJlc3VsdHMgdGhhdCBjb3VsZCBoZWxwIHlvdSBmdWxmaWxsIHRoaXMgcmVxdWVzdDpcblxuMS4gKipJZGVudGlmeSBZb3VyIFByZWZlcmVuY2VzOioqXG4gICAtIERldGVybWluZSB0aGUgdHlwZSBvZiBzaG9lcyB5b3UgbmVlZCAoZS5nLiwgc25lYWtlcnMsIGRyZXNzIHNob2VzLCBib290cykuXG4gICAtIENvbnNpZGVyIGFueSBzcGVjaWZpYyBicmFuZHMgb3Igc3R5bGVzIHlvdSBwcmVmZXIuXG5cbjIuICoqU2V0IGEgQnVkZ2V0OioqXG4gICAtIERlY2lkZSBob3cgbXVjaCB5b3UncmUgd2lsbGluZyB0byBzcGVuZCBvbiB0aGUgc2hvZXMuXG5cbjMuICoqUmVzZWFyY2g6KipcbiAgIC0gVmlzaXQgb25saW5lIHJldGFpbCB3ZWJzaXRlcyBzdWNoIGFzIEFtYXpvbiwgWmFwcG9zLCBOaWtlLCBvciBzcGVjaWZpYyBicmFuZCBzaXRlcy5cbiAgIC0gQ2hlY2sgZm9yIGFueSBvbmdvaW5nIHNhbGVzIG9yIGRpc2NvdW50cy5cblxuNC4gKipWaXNpdCBQaHlzaWNhbCBTdG9yZXM6KipcbiAgIC0gSWYgeW91IHByZWZlciB0cnlpbmcgc2hvZXMgb24gYmVmb3JlIHB1cmNoYXNpbmcsIHZpc2l0IGxvY2FsIHNob2Ugc3RvcmVzIG9yIGRlcGFydG1lbnQgc3RvcmVzLlxuXG41LiAqKk9ubGluZSBQbGF0Zm9ybXM6KipcbiAgIC0gVXNlIGUtY29tbWVyY2UgcGxhdGZvcm1zIGxpa2UgQW1hem9uLCBlQmF5LCBvciBzcGVjaWFsaXplZCBzaG9lIHJldGFpbGVycy5cblxuNi4gKipSZWFkIFJldmlld3M6KipcbiAgIC0gQ2hlY2sgY3VzdG9tZXIgcmV2aWV3cyBhbmQgcmF0aW5ncyB0byBlbnN1cmUgcXVhbGl0eSBhbmQgZml0LlxuXG43LiAqKkNvbnNpZGVyIFNpemVzOioqXG4gICAtIEVuc3VyZSB5b3Uga25vdyB5b3VyIHNob2Ugc2l6ZS4gQ2hlY2sgaWYgdGhlIHNwZWNpZmljIGJyYW5kIG9yIHR5cGUgb2Ygc2hvZSBmaXRzIHRydWUgdG8gc2l6ZS5cblxuOC4gKipQdXJjaGFzZToqKlxuICAgLSBPbmNlIHlvdSd2ZSBmb3VuZCBhIHBhaXIgdGhhdCBtYXRjaGVzIHlvdXIgcHJlZmVyZW5jZXMgYW5kIGJ1ZGdldCwgZ28gYWhlYWQgYW5kIG1ha2UgdGhlIHB1cmNoYXNlLlxuXG45LiAqKlNoaXBwaW5nIGFuZCBSZXR1cm5zOioqXG4gICAtIENoZWNrIHRoZSBzaGlwcGluZyBvcHRpb25zIGFuZCB0aGUgcmV0dXJuIHBvbGljeSBpbiBjYXNlIHRoZSBzaG9lcyBkbyBub3QgZml0IG9yIG1lZXQgeW91ciBleHBlY3RhdGlvbnMuXG5cbklmIHlvdSBoYXZlIG1vcmUgc3BlY2lmaWMgY3JpdGVyaWEgb3IgcmVxdWlyZSBhc3Npc3RhbmNlIHdpdGggc3BlY2lmaWMgc3RvcmVzIG9yIGJyYW5kcywgZmVlbCBmcmVlIHRvIHByb3ZpZGUgYWRkaXRpb25hbCBkZXRhaWxzISJ9","expires":null,"nonce":null,"signature":"sig1lsc7kttap4utjfuhs0w34vy396vse2tuekyw6aak77hr9sdwj967u3u3u96l9c20yzn25qgsw70pjtd4tn2hgtlmp8x7u39ad9jhurcgaru0n"} INFO:fetchai:Got response looking up agent endpoint https://staging-api.flockx.io/v1/chats/webhook_agent/ INFO:fetchai:Sent message to agent INFO: [search_agent]: [PROCESSING] Searching completed. Sending response back to the query agent. INFO: [bureau]: Starting server on http://0.0.0.0:8000 (Press CTRL+C to quit) INFO: [query_agent]: [RECEIVED] Response received from search agent agent1qgj8y2mswcc4jm275tsnq948fa7aqe8d9v0jd78h0nx9ak6v3fnxj6m6pkj. Status: 'Agent searched'
Last updated on