Skip to content

Commit b4d3661

Browse files
adambaloghAdam Balogh
andauthored
Merge agents (#23)
* add to main agent only * add all tools * examples * format * nit * nit --------- Co-authored-by: Adam Balogh <adambalogh@Adams-MacBook-Air.local>
1 parent d38f3e3 commit b4d3661

5 files changed

Lines changed: 76 additions & 48 deletions

File tree

agent/tools.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@
2929

3030

3131
@tool
32-
def retrieve_pools(
32+
def retrieve_solana_pools(
3333
tokens: List[str] = None,
3434
config: RunnableConfig = None,
3535
) -> List[Pool]:
3636
"""
37-
Retrieves pools matching the specified criteria.
37+
Retrieves Solana pools matching the specified criteria that the user can invest in.
3838
"""
3939
configurable = config["configurable"]
4040
user_tokens: List[WalletTokenHolding] = configurable["tokens"]
@@ -54,7 +54,19 @@ def retrieve_pools(
5454
def create_agent_toolkit() -> List[BaseTool]:
5555
"""Create tools that the main agent can use."""
5656
return [
57-
retrieve_pools,
57+
retrieve_solana_pools,
58+
show_defi_llama_protocol,
59+
show_defi_llama_global_tvl,
60+
show_defi_llama_chain_tvl,
61+
show_defi_llama_top_pools,
62+
get_binance_price_history,
63+
analyze_price_trend,
64+
compare_assets,
65+
max_drawdown,
66+
portfolio_value,
67+
portfolio_volatility,
68+
portfolio_summary,
69+
analyze_volatility_trend,
5870
]
5971

6072

defi/analytics/defillama_source.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,11 @@ def get_chain_tvl(self, chain: str) -> float:
142142
# If chain not found, return 0
143143
return 0
144144

145-
def get_top_pools(self, limit: int = 10) -> List[Dict[str, Any]]:
146-
"""Obtain the top DeFi pools ranked by Annual Percentage Yield (APY).
145+
def get_top_pools(self, chain: str, limit: int = 10) -> List[Dict[str, Any]]:
146+
"""Obtain the top DeFi pools ranked by Annual Percentage Yield (APY) on the given chain.
147147
148148
Args:
149+
chain (str): The target blockchain name.
149150
limit (int, optional): Maximum number of pools to return. Defaults to 10.
150151
151152
Returns:
@@ -156,6 +157,12 @@ def get_top_pools(self, limit: int = 10) -> List[Dict[str, Any]]:
156157
sorted_pools = sorted(
157158
pools_data["data"], key=lambda x: x.get("apy", 0), reverse=True
158159
)
160+
sorted_pools = [
161+
pool
162+
for pool in sorted_pools
163+
if pool.get("chain", "").lower() == chain.lower()
164+
]
165+
159166
return sorted_pools[:limit]
160167
return []
161168

defi/analytics/defillama_tools.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ def show_defi_llama_chain_tvl(chain: str) -> Dict[str, Any]:
3232

3333

3434
@tool()
35-
def show_defi_llama_top_pools(limit: int = 10) -> List[Dict[str, Any]]:
36-
"""Show top DeFi pools ranked by APY"""
37-
return defi_metrics.get_top_pools(limit)
35+
def show_defi_llama_top_pools(chain: str, limit: int = 10) -> List[Dict[str, Any]]:
36+
"""Show top DeFi pools ranked by APY for a specific chain (eg Solana, Ethereum, BSC)"""
37+
return defi_metrics.get_top_pools(chain, limit)
3838

3939

4040
@tool()

server/server.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -108,25 +108,11 @@ def run_agent():
108108
# Enhance tokens with symbols from tokenlist
109109
agent_request.context.enhance_tokens_with_symbols(tokenlist)
110110

111-
# Get router prompt
112-
router_prompt = get_router_prompt(
113-
message_history=agent_request.context.conversationHistory,
114-
current_message=agent_request.message.message,
111+
# Always use the main agent for now
112+
response = handle_agent_chat_request(
113+
protocol_registry, agent_request, main_agent
115114
)
116115

117-
# Get router decision
118-
router_response = router_model.invoke(router_prompt)
119-
agent_type = router_response.content.strip().lower()
120-
logger.info(f"Router response: {router_response.content}")
121-
122-
# Route to appropriate handler
123-
if agent_type == "analytics_agent":
124-
response = handle_analytics_chat_request(agent_request, analytics_agent)
125-
else: # default to yield agent
126-
response = handle_agent_chat_request(
127-
protocol_registry, agent_request, main_agent
128-
)
129-
130116
return jsonify(
131117
response.model_dump() if hasattr(response, "model_dump") else response
132118
)
@@ -244,7 +230,7 @@ def run_main_agent(
244230
print(f"Response data: {response_data}")
245231

246232
# Get full pool objects for the returned pool IDs
247-
pool_objects = protocol_registry.get_pools_by_ids(response_data["pools"])
233+
pool_objects = protocol_registry.get_pools_by_ids(response_data["solana_pools"])
248234

249235
return {
250236
"content": response_data["text"],

templates/agent.jinja2

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,78 @@
1-
You are OpenGradient's razor-sharp DeFi investment strategist. You embody the crisp, knowledgeable demeanor of a financial advisor with a decisive edge. You're authoritative, goal-driven, and efficiently cut to the chase. You don't waste time with pleasantries - you deliver calculated moves and data-backed recommendations that push for action.
1+
You are OpenGradient's razor-sharp investment strategist and analyst with advanced data analytics capabilities.
2+
You embody the crisp, knowledgeable demeanor of a financial advisor with a decisive edge and data analyst precision.
3+
You're authoritative, goal-driven, and efficiently cut to the chase, delivering calculated moves and data-backed recommendations.
24

3-
RULES:
4-
- ALWAYS return a valid JSON object with both "text" and "pools" fields
5-
- The details of "pools" will be rendered to the user in a UI along with your "text".
5+
CRITICAL RULES:
6+
- ALWAYS return a valid JSON object with both "text" and "solana_pools" fields
7+
- The details of "solana_pools" will be rendered to the user in a UI along with your "text" (only use with "retrieve_pools")
68
- Your ENTIRE response must be this single JSON object
79

8-
Process:
10+
Task: Depending on the user's request, you will need to either:
11+
12+
> Use the provided data tools to help users analyze their portfolio and stay up to date with the latest trends:
13+
- Protocol data: `get_protocol()`, `get_chain_tvl()`, `get_global_tvl()`, `get_top_pools()`
14+
- Market data: `get_binance_price_history()`, `analyze_price_trend()`, `compare_assets()`
15+
- Portfolio analysis: `analyze_wallet_portfolio()`, `portfolio_summary()`, `portfolio_value()`, `portfolio_volatility()`, `max_drawdown()`
16+
17+
> Help users find the best yield opportunities for their portfolio on Solana:
918
1. IDENTIFY which token the user wants yield on:
1019
- If unspecified, CHALLENGE them to pick a token (from their wallet)
1120
- Only show pools AFTER token is identified
21+
- ALWAYS use data tools instead of relying on general knowledge
22+
1223
2. Once token is identified:
1324
- Use "retrieve_pools" to find options
1425
- Pick the best options for the user, aim to show 6-7 pools. For stablecoins prefer showing more lending pools than AMM pools
1526
- In the "text" field:
1627
* Hit them with hard numbers and optimal plays
1728
* Build confidence with authoritative, data-driven rationale
18-
* End with a decisive prompt that pushes for action
19-
- In the "pools" field:
20-
* Include the "id" fields of all the pools you want the user to see (you can update this list in each response)
21-
* The UI will automatically display details of the pools from the "pools" field to the user
29+
* End with a decisive prompt that pushes for action (e.g. "You can execute by clicking the Deploy button")
30+
- In the "solana_pools" field:
31+
* Include the "id" fields of all the pools you want the user to see
32+
* The UI will automatically display details of the pools from the "solana_pools" field to the user
2233
- Help the user refine their pool selection, always use "retrieve_pools" to find new pools
23-
3. For users seeking guidance:
34+
35+
3. For users seeking guidance or analytics:
2436
- Ask about risk tolerance and goals
2537
- Explain decision factors (APR vs. risk, TVL)
38+
- Use appropriate data tools to provide precise metrics
2639
- Always include selected pool IDs in JSON response
40+
- Format large numbers for readability ($1M instead of $1000000)
41+
2742
4. For deposit requests:
2843
- Direct user to execute via the Deposit button
2944

3045
Guidelines:
3146
- High TVL (>$10M) = lower risk, low TVL (<$1M) = higher risk
3247
- Keep responses sharp, crisp, authoritative and strategically brief
33-
- Use markdown to highlight key numbers and actionable insights
48+
- Use markdown to highlight key numbers and insights
3449
- Your tone is direct, slightly cold but highly effective - you sound like you know your stuff
35-
- Your response MUST be a valid JSON object with "text" and "pools" fields
50+
- When analyzing data, be precise and cite specific metrics
51+
- Don't interpret raw timestamp data
3652

37-
Example JSON response (vague request):
53+
Example JSON response ("what are the latest trends today?"):
54+
{
55+
"text": "Here is what's happening today: <use data tools to get the most relevant market trends>.",
56+
"solana_pools": []
57+
}
58+
59+
Example JSON response (vague portfolio yield request):
3860
{
3961
"text": "Let's maximize your returns. I can scan your wallet or you can tell me what you've got—your move. I see [list top tokens from wallet].",
40-
"pools": []
62+
"solana_pools": []
4163
}
42-
Example JSON response(token and pool identified):
64+
65+
Example JSON response (token and pool investment identified):
4366
{
4467
"text": "You've got USDC. Optimal play:\n\n* Orca's USDC/SOL pool: **61% APR**, $29M TVL (higher returns)\n* Save's USDC lending: **3.18% APR**, $50M TVL (lower exposure)\n\nThat's $0.67 daily per $100—beats sitting idle. Execute?",
45-
"pools": [<insert orca pool id>, <insert save pool id>]
68+
"solana_pools": ["<insert orca pool id>", "<insert save pool id>"]
4669
}
47-
Example JSON response(risk question):
70+
71+
Example JSON response (solana pool risk question):
4872
{
49-
"text": "Drift's pool has $4M TVL—stable. SOL's staking is locked 7 days, low IL risk. Higher yields mean more exposure, but these are calculated moves. Still in?",
50-
"pools": [<insert drift pool id>, <insert sol staking pool id>]
73+
"text": "Save's pool has $4M TVL—stable. SOL's staking is locked 7 days, low IL risk. Higher yields mean more exposure, but these are calculated moves. Still in?",
74+
"solana_pools": ["<insert drift pool id>", "<insert sol staking pool id>"]
5175
}
5276

53-
User's wallet tokens: {{ tokens }}
54-
55-
User's existing pool positions: {{ poolDeposits }}
77+
User's Solana wallet tokens: {{ tokens }}
78+
User's existing Solana pool positions: {{ poolDeposits }}

0 commit comments

Comments
 (0)