Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gemini-research-agent/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Add your Google Gemini API key here
GEMINI_API_KEY=your_api_key_here
1 change: 1 addition & 0 deletions gemini-research-agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
43 changes: 43 additions & 0 deletions gemini-research-agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Gemin# Gemini-Powered Research Agent

This example demonstrates how to integrate Google's Gemini API (`google-genai`) within the Fetch.ai `uagents` framework to create an autonomous research and summarization agent.

## Architecture
This example utilizes two agents:

1. **Gemini Agent (`gemini_agent.py`)**: Acts as the backend processor. It listens for `ResearchRequest` messages, queries the Gemini 2.5 Flash model, and returns a structured `ResearchResponse`.
2. **User Agent (`user_agent.py`)**: Acts as the client. It triggers the request on startup and logs the AI-generated summary upon receipt.

## Prerequisites
Ensure you have Python 3.10+ installed.

Install the required dependencies:
```bash
python -m pip install uagents google-genai python-dotenv
```

## Setup Instructions

### 1. API Key Setup
Create a `.env` file in this directory and add your Google Gemini API key:
```text
GEMINI_API_KEY=your_api_key_here
```

### 2. Start the Gemini Agent
Open a terminal and run the Gemini agent:
```bash
python gemini_agent.py
```
*Note: Look at the startup logs and copy the Agent address (it starts with `agent1...`).*

### 3. Configure the User Agent
Open `user_agent.py` and replace the `TARGET_AGENT_ADDRESS` variable with the address you just copied.

### 4. Trigger the Research
Open a second terminal and run the user agent:
```bash
python user_agent.py
```

You will see the asynchronous message transfer and the final AI-generated summary printed in your terminal!
Binary file added gemini-research-agent/assets/demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 88 additions & 0 deletions gemini-research-agent/gemini_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from datetime import datetime
from uuid import uuid4
from uagents import Agent, Context, Protocol
from uagents_core.contrib.protocols.chat import (
ChatMessage,
ChatAcknowledgement,
TextContent,
chat_protocol_spec,
)
from google import genai
from dotenv import load_dotenv

# Load environment variables (ensure GEMINI_API_KEY is in your .env)
load_dotenv()

# --- 1. Initialize the Agent ---
research_agent = Agent(
name="gemini_researcher",
port=8000,
seed="gemini_researcher_secret_seed",
endpoint=["http://127.0.0.1:8000/submit"],
)

# Initialize the chat protocol
chat_proto = Protocol(spec=chat_protocol_spec)

# Initialize the Gemini Client
gemini_client = genai.Client()

# --- 2. Define the Message Handlers ---
@chat_proto.on_message(ChatMessage)
async def handle_research_request(ctx: Context, sender: str, msg: ChatMessage):
# Send an immediate acknowledgment that the message was received
ack = ChatAcknowledgement(
timestamp=datetime.utcnow(),
acknowledged_msg_id=msg.msg_id
)
await ctx.send(sender, ack)

# Extract the text content from the ChatMessage
for item in msg.content:
if isinstance(item, TextContent):
user_query = item.text
ctx.logger.info(f"Received research request from {sender[-8:]} for topic: '{user_query}'")

try:
# Prompt Engineering for the Agent
system_instruction = "You are a concise, highly factual research assistant."
prompt = (
f"{system_instruction}\n\nProvide a structured summary about: {user_query}"
)

# Call the Gemini API
response = gemini_client.models.generate_content(
model="gemini-2.5-flash",
contents=prompt,
)

# Package the AI-generated response into a ChatMessage
response_msg = ChatMessage(
timestamp=datetime.utcnow(),
msg_id=uuid4(),
content=[TextContent(type="text", text=response.text)]
)

await ctx.send(sender, response_msg)
ctx.logger.info("Successfully generated and returned the research summary.")

except Exception as e:
ctx.logger.error(f"Gemini API Error: {e}")

# Package the error into a ChatMessage
error_msg = ChatMessage(
timestamp=datetime.utcnow(),
msg_id=uuid4(),
content=[TextContent(type="text", text=f"Agent Error: Could not process request. {str(e)}")]
)
await ctx.send(sender, error_msg)

@chat_proto.on_message(ChatAcknowledgement)
async def handle_acknowledgement(ctx: Context, sender: str, msg: ChatAcknowledgement):
ctx.logger.info(f"Received acknowledgement from {sender} for message: {msg.acknowledged_msg_id}")

# Include the protocol in your agent
research_agent.include(chat_proto, publish_manifest=True)

if __name__ == "__main__":
research_agent.run()
4 changes: 4 additions & 0 deletions gemini-research-agent/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
uagents
uagents-core
google-genai
python-dotenv
74 changes: 74 additions & 0 deletions gemini-research-agent/user_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import asyncio
from datetime import datetime
from uuid import uuid4
from uagents import Agent, Context, Protocol
from uagents_core.contrib.protocols.chat import (
ChatMessage,
ChatAcknowledgement,
TextContent,
chat_protocol_spec,
)

# --- THE FIX: Manually jumpstart the asyncio event loop for Python 3.12+ ---
try:
asyncio.get_event_loop()
except RuntimeError:
asyncio.set_event_loop(asyncio.new_event_loop())

# --- 1. Initialize the User Agent ---
user_agent = Agent(
name="user_client",
port=8001,
seed="user_client_secret_seed",
endpoint=["http://127.0.0.1:8001/submit"],
)

# Initialize the chat protocol
chat_proto = Protocol(spec=chat_protocol_spec)

# YOUR TARGET ADDRESS
TARGET_AGENT_ADDRESS = (
"agent1qtjys8khgg88v6gvjudrlxdp7njxn9utettjclyj68pfevm7df9e6nsseng"
)

# --- 2. Define the Triggers and Handlers ---
@user_agent.on_event("startup")
async def send_research_request(ctx: Context):
topic = "The architecture of transformer-based Large Language Models"
ctx.logger.info(f"Sending research request for: {topic}")

# Package the prompt into a TextContent object inside a ChatMessage
research_message = ChatMessage(
timestamp=datetime.utcnow(),
msg_id=uuid4(),
content=[TextContent(type="text", text=topic)]
)

# Send the request to the Gemini Agent
await ctx.send(TARGET_AGENT_ADDRESS, research_message)

@chat_proto.on_message(ChatMessage)
async def handle_response(ctx: Context, sender: str, msg: ChatMessage):
# Extract the summary text from the incoming ChatMessage
for item in msg.content:
if isinstance(item, TextContent):
ctx.logger.info("\n=== Received Research Summary ===")
ctx.logger.info(item.text)
ctx.logger.info("=================================\n")

# Send an acknowledgment back to the Gemini agent
ack = ChatAcknowledgement(
timestamp=datetime.utcnow(),
acknowledged_msg_id=msg.msg_id
)
await ctx.send(sender, ack)

@chat_proto.on_message(ChatAcknowledgement)
async def handle_acknowledgement(ctx: Context, sender: str, msg: ChatAcknowledgement):
ctx.logger.info(f"Received acknowledgement from {sender} for message: {msg.acknowledged_msg_id}")

# Include the protocol in your agent
user_agent.include(chat_proto, publish_manifest=True)

if __name__ == "__main__":
user_agent.run()