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
38 changes: 22 additions & 16 deletions Browser-based-agents/Notte-labs-agent/Nike-products-agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import os
from enum import Enum
import asyncio

from uagents import Agent, Context, Model
from uagents.experimental.quota import QuotaProtocol, RateLimit
Expand All @@ -17,11 +16,7 @@
from nike_scraper import get_nike_info_enhanced, NikeScrapeRequest, NikeScrapeResponse

# Create the agent with mailbox=True for ASI1 discoverability
agent = Agent(
name="nike_scraper",
port=8000,
mailbox=True
)
agent = Agent(name="nike_scraper", port=8000, mailbox=True)

# Print the agent's address for reference
print(f"Your Nike Scraper agent's address is: {agent.address}")
Expand All @@ -34,29 +29,31 @@
default_rate_limit=RateLimit(window_size_minutes=60, max_requests=30),
)


# Handle direct Nike scraper requests (without natural language processing)
@proto.on_message(
NikeScrapeRequest, replies={NikeScrapeResponse, ErrorMessage}
)
@proto.on_message(NikeScrapeRequest, replies={NikeScrapeResponse, ErrorMessage})
async def handle_request(ctx: Context, sender: str, msg: NikeScrapeRequest):
"""
Handle direct structured requests for Nike product information.
This allows other agents to communicate directly with this agent
using the NikeScrapeRequest model.
"""
ctx.logger.info(f"Received Nike scrape request: action={msg.action}, category={msg.category_name}")

ctx.logger.info(
f"Received Nike scrape request: action={msg.action}, category={msg.category_name}"
)

try:
# Process the request using the nike_scraper module
nike_response = await get_nike_info_enhanced(request=msg)
ctx.logger.info(f"Successfully processed Nike request")

ctx.logger.info("Successfully processed Nike request")
await ctx.send(sender, NikeScrapeResponse(results=nike_response.results))

except Exception as err:
ctx.logger.error(f"Error in handle_request: {err}")
await ctx.send(sender, ErrorMessage(error=str(err)))


# Health check functionality
def agent_is_healthy() -> bool:
"""
Expand All @@ -65,26 +62,32 @@ def agent_is_healthy() -> bool:
"""
try:
import requests

response = requests.get("https://www.nike.com", timeout=5)
return response.status_code == 200
except Exception:
return False


class HealthCheck(Model):
pass


class HealthStatus(str, Enum):
HEALTHY = "healthy"
UNHEALTHY = "unhealthy"


class AgentHealth(Model):
agent_name: str
status: HealthStatus


health_protocol = QuotaProtocol(
storage_reference=agent.storage, name="HealthProtocol", version="0.1.0"
)


@health_protocol.on_message(HealthCheck, replies={AgentHealth})
async def handle_health_check(ctx: Context, sender: str, msg: HealthCheck):
"""Handle health check requests to monitor agent status."""
Expand All @@ -97,6 +100,7 @@ async def handle_health_check(ctx: Context, sender: str, msg: HealthCheck):
finally:
await ctx.send(sender, AgentHealth(agent_name="nike_scraper", status=status))


# Register all protocols with the agent
agent.include(proto, publish_manifest=True)
agent.include(health_protocol, publish_manifest=True)
Expand All @@ -108,10 +112,12 @@ async def handle_health_check(ctx: Context, sender: str, msg: HealthCheck):
if not os.environ.get("NOTTE_API_KEY"):
print("Warning: NOTTE_API_KEY environment variable is not set.")
print("The agent will run but scraping functionality will be limited.")

# Run the agent
print("Starting Nike Scraper Agent...")
print("This agent can respond to natural language queries about Nike products via ASI1 LLM.")
print(
"This agent can respond to natural language queries about Nike products via ASI1 LLM."
)
print("Example queries:")
print("- Show me Nike categories")
print("- List Nike basketball shoes")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
chat_protocol_spec,
)

from nike_scraper import get_nike_info_enhanced, NikeScrapeRequest, NikeScrapeResponse
from nike_scraper import get_nike_info_enhanced, NikeScrapeRequest

# Replace the AI Agent Address with one of the LLMs that support StructuredOutput
# OpenAI Agent: agent1q0h70caed8ax769shpemapzkyk65uscw4xwk6dc4t3emvp5jdcvqs9xs32y
# Claude.ai Agent: agent1qvk7q2av3e2y5gf5s90nfzkc8a48q3wdqeevwrtgqfdl0k78rspd6f2l4dx
AI_AGENT_ADDRESS = 'agent1qtlpfshtlcxekgrfcpmv7m9zpajuwu7d5jfyachvpa4u3dkt6k0uwwp2lct'
AI_AGENT_ADDRESS = "agent1qtlpfshtlcxekgrfcpmv7m9zpajuwu7d5jfyachvpa4u3dkt6k0uwwp2lct"

if not AI_AGENT_ADDRESS:
raise ValueError("AI_AGENT_ADDRESS not set")
Expand Down Expand Up @@ -69,7 +69,9 @@ async def handle_message(ctx: Context, sender: str, msg: ChatMessage):
ctx.storage.set(str(ctx.session), sender)
await ctx.send(
sender,
ChatAcknowledgement(timestamp=datetime.utcnow(), acknowledged_msg_id=msg.msg_id),
ChatAcknowledgement(
timestamp=datetime.utcnow(), acknowledged_msg_id=msg.msg_id
),
)

for item in msg.content:
Expand Down Expand Up @@ -110,7 +112,12 @@ async def handle_structured_output_response(
return

# Check for empty or clearly invalid output from LLM
if not msg.output or "<UNKNOWN>" in str(msg.output) or not isinstance(msg.output, dict) or not msg.output.get('action'):
if (
not msg.output
or "<UNKNOWN>" in str(msg.output)
or not isinstance(msg.output, dict)
or not msg.output.get("action")
):
await ctx.send(
session_sender,
create_text_chat(
Expand All @@ -123,7 +130,7 @@ async def handle_structured_output_response(
# Parse the structured output from the LLM
try:
request = NikeScrapeRequest.parse_obj(msg.output)
except Exception as p_err: # Catch Pydantic validation errors or others
except Exception as p_err: # Catch Pydantic validation errors or others
ctx.logger.error(f"Error parsing LLM output: {msg.output}. Error: {p_err}")
await ctx.send(
session_sender,
Expand All @@ -132,14 +139,14 @@ async def handle_structured_output_response(
),
)
return

# Get the Nike information based on the structured request
nike_response = await get_nike_info_enhanced(request=request)

# Send the response back to the user
chat_message = create_text_chat(nike_response.results)
await ctx.send(session_sender, chat_message)

except Exception as err:
ctx.logger.error(f"Error processing Nike request: {err}")
await ctx.send(
Expand Down
Loading
Loading