Add AI Crypto Price Alert Agent#22
Conversation
|
|
||
| def get_price(coin_id): | ||
| url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies=usd" | ||
| response = requests.get(url) |
There was a problem hiding this comment.
Bug: The asynchronous check_price function uses a blocking requests.get() call without a timeout, which will freeze the agent and make it unresponsive during the API request.
Severity: CRITICAL
Suggested Fix
Replace the synchronous requests.get() call with an asynchronous HTTP client library like aiohttp. Alternatively, if requests must be used, wrap the blocking call in asyncio.to_thread() to run it in a separate thread without blocking the main event loop. In either case, a reasonable timeout should be added to all network requests to prevent indefinite hangs.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: Crypto-Price-Alert-Agent/agent.py#L14
Potential issue: The `check_price` function is an asynchronous interval handler that
uses the synchronous `requests.get()` library to make an HTTP call. This is a blocking
I/O operation that will freeze the agent's entire asyncio event loop while it waits for
the network response. During this time, the agent will be unable to process any other
tasks, such as incoming messages or other scheduled intervals. Furthermore, the
`requests.get()` call does not have a `timeout` parameter, creating a risk that the
agent could hang indefinitely if the external API is slow or unresponsive, causing it to
miss subsequent checks.
Did we get this right? 👍 / 👎 to inform future reviews.
Review: Add AI Crypto Price Alert AgentSummaryThis PR adds a new example agent that monitors cryptocurrency prices via the CoinGecko API and logs alerts when Bitcoin drops below a configurable threshold. The agent uses the Overall risk: Low — This is an example agent with no external dependencies beyond What I liked
SecurityHardcoded seed phrase (blocking for production, acceptable for example)
crypto_agent = Agent(name="crypto_watcher", seed="Cripto_Watcher_24")Why this matters: The seed deterministically generates the agent's address and its on-chain wallet. Anyone with the seed can impersonate the agent and drain any FET associated with that address. For an example: This is acceptable as-is, but I'd recommend adding a comment explaining this should come from an environment variable in production: # Replace "your_seed_phrase" with any random text
# In production, load from os.environ["AGENT_SEED_PHRASE"]
crypto_agent = Agent(name="crypto_watcher", seed="Cripto_Watcher_24")Correctness & logicMissing HTTP error handling
def get_price(coin_id):
url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies=usd"
response = requests.get(url)
data = response.json() # Will raise if status != 200
return data[coin_id]['usd']If CoinGecko returns a 429 (rate limit), 500, or other error, Suggested fix: def get_price(coin_id):
url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies=usd"
response = requests.get(url)
response.raise_for_status() # Raise HTTPError for bad responses
data = response.json()
return data[coin_id]['usd']Potential KeyError on malformed response
Suggested fix: def get_price(coin_id):
url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies=usd"
response = requests.get(url)
response.raise_for_status()
data = response.json()
if coin_id not in data or 'usd' not in data[coin_id]:
raise ValueError(f"Unexpected API response structure: {data}")
return data[coin_id]['usd']PerformanceBlocking HTTP call in async handler
Why this matters: For a simple example with one agent and one interval, this is fine. But if this pattern were scaled (multiple agents, concurrent message handling), blocking calls would stall all other work. Suggested fix (for production patterns): import aiohttp
async def get_price(coin_id):
url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies=usd"
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
response.raise_for_status()
data = await response.json()
if coin_id not in data or 'usd' not in data[coin_id]:
raise ValueError(f"Unexpected API response structure: {data}")
return data[coin_id]['usd']For this example, the synchronous approach is acceptable — but a comment explaining the tradeoff would be helpful for learners. Code qualityMissing
|
| # 1. Define your Agent | ||
| # Replace "your_seed_phrase" with any random text | ||
| crypto_agent = Agent(name="crypto_watcher", seed="Cripto_Watcher_24") | ||
|
|
There was a problem hiding this comment.
| # Replace "your_seed_phrase" with any random text | |
| # In production, load from os.environ["AGENT_SEED_PHRASE"] | |
| crypto_agent = Agent(name="crypto_watcher", seed="Cripto_Watcher_24") |
| def get_price(coin_id): | ||
| url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies=usd" | ||
| response = requests.get(url) | ||
| data = response.json() |
There was a problem hiding this comment.
| data = response.json() | |
| def get_price(coin_id): | |
| url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies=usd" | |
| response = requests.get(url) | |
| response.raise_for_status() # Raise HTTPError for bad responses | |
| data = response.json() | |
| return data[coin_id]['usd'] |
Summary
Describe what this PR changes.
Type of Change
Checklist
ruff check ..ruff format ..README.mdfor changed example(s)..env.exampleif environment variables are required.CHANGELOG.md(required for non-doc changes).Related Issue
Link issue number(s), if any:
Notes for Reviewers
This agent is a great entry-level example for users learning how to integrate external APIs (CoinGecko) with the uAgents framework. It focuses on the on_interval decorator and basic logging.