Skip to content

Commit 0cce807

Browse files
committed
System prompt v2
1 parent 3df62ac commit 0cce807

2 files changed

Lines changed: 131 additions & 95 deletions

File tree

app/api/trade/route.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { NextResponse } from "next/server";
22
import { BALANCE_UPDATE_DELAY, logTradingAgentData } from "@/lib/utils";
33
import { storeTrade, storePortfolioSnapshot } from "@/lib/api-helpers";
44
import { buildTransactionPayload, initializeNearAccount } from "@/lib/near";
5-
import { buildAgentContext } from "@/lib/agent-context";
5+
import { AGENT_TRIGGER_MESSAGE, buildAgentContext } from "@/lib/agent-context";
66
import { callAgent } from "@bitte-ai/agent-sdk";
77
import { ToolResult } from "@/lib/types";
88
import { withCronSecret } from "@/lib/api-auth";
@@ -17,11 +17,12 @@ async function tradeHandler(): Promise<NextResponse> {
1717

1818
const context = await buildAgentContext(accountId, account);
1919

20-
const { content, toolResults } = await callAgent(
20+
const { content, toolResults } = await callAgent({
2121
accountId,
22-
context.systemPrompt,
22+
message: AGENT_TRIGGER_MESSAGE,
2323
agentId,
24-
);
24+
systemPrompt: context.systemPrompt
25+
});
2526

2627
const quoteResult = (toolResults as ToolResult[]).find(
2728
(callResult) => callResult.result?.data?.data?.quote,

lib/agent-context.ts

Lines changed: 126 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -87,106 +87,141 @@ function createUsdcPosition(
8787
}
8888

8989
function generateSystemPrompt(
90-
totalUsd: number,
91-
pnlUsd: number,
92-
pnlPercent: number,
93-
positionsWithPnl: PositionWithPnL[],
94-
marketOverviewData: string,
90+
totalUsd: number,
91+
pnlUsd: number,
92+
pnlPercent: number,
93+
positionsWithPnl: PositionWithPnL[],
94+
marketOverviewData: string,
9595
): string {
96-
const strategy = getEnvStrategy();
97-
return `
96+
const strategy = getEnvStrategy();
97+
98+
const tradingPositions = positionsWithPnl.filter(
99+
(pos) => pos.symbol !== "USDC" && Number(pos.rawBalance) >= 1000
100+
);
101+
const usdcPosition = positionsWithPnl.find((pos) => pos.symbol === "USDC");
102+
103+
104+
return `
105+
106+
🤖 AUTONOMOUS TRADING AGENT - ONE-SHOT EXECUTION
107+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
108+
109+
CRITICAL: You have ONE response to analyze and execute.
110+
If you decide to trade, you MUST call QUOTE in THIS response.
111+
There is no "next time" - trades not executed now will NOT happen.
112+
113+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
114+
PORTFOLIO STATUS
115+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
116+
Total Value: $${totalUsd.toFixed(2)}
117+
Overall P&L: ${pnlUsd >= 0 ? "+" : ""}$${pnlUsd.toFixed(2)} (${pnlPercent >= 0 ? "+" : ""}${pnlPercent.toFixed(2)}%)
118+
119+
┌─ OPEN POSITIONS ─────────────────────────────────────┐
120+
${tradingPositions.length > 0 ? tradingPositions.map((pos) => {
121+
const exitSignal = pos.pnl_percent >= strategy.riskParams.profitTarget
122+
? "🟢 PROFIT"
123+
: pos.pnl_percent <= strategy.riskParams.stopLoss
124+
? "🔴 STOP"
125+
: "⚪ HOLD";
126+
127+
return `│ ${pos.symbol.padEnd(6)} [${exitSignal}] P&L: ${(pos.pnl_percent >= 0 ? "+" : "")}${pos.pnl_percent.toFixed(2)}%
128+
│ Entry: $${pos.avgEntryPrice.toFixed(4)} → Current: $${pos.currentPrice.toFixed(4)}
129+
│ Value: $${pos.usd_value.toFixed(2)}
130+
│ QUOTE amount: "${pos.rawBalance}"`;
131+
}).join("\n│\n") : "│ No positions"}
132+
└──────────────────────────────────────────────────────┘
133+
134+
Available USDC: $${(usdcPosition?.usd_value || 0).toFixed(2)}
135+
QUOTE amount: "${usdcPosition?.rawBalance || "0"}"
136+
137+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
138+
MARKET CONDITIONS
139+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
140+
${marketOverviewData}
98141
99-
=== PORTFOLIO DATA ===
100-
TOTAL VALUE: $${totalUsd.toFixed(2)} | OVERALL PNL: ${pnlUsd >= 0 ? "+" : ""}$${pnlUsd.toFixed(2)} (${pnlPercent >= 0 ? "+" : ""}${pnlPercent.toFixed(2)}%)
142+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
143+
TRADING STRATEGY: ${strategy.overview}
144+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
101145
102-
OPEN POSITIONS:
103-
${positionsWithPnl
104-
.filter((pos) => pos.symbol !== "USDC" && Number(pos.rawBalance) >= 1000)
105-
.map((pos) => {
106-
return `${pos.symbol}: ${pos.balance} tokens | RAW_BALANCE=${pos.rawBalance} | Entry: $${pos.avgEntryPrice.toFixed(4)} | Current: $${pos.currentPrice.toFixed(4)} | Value: $${pos.usd_value.toFixed(2)} | PNL: ${pos.pnl_usd >= 0 ? "+" : ""}$${pos.pnl_usd.toFixed(2)} (${pos.pnl_percent >= 0 ? "+" : ""}${pos.pnl_percent.toFixed(1)}%)`;
107-
})
108-
.join("\n")}
146+
STEP 1: PORTFOLIO RISK MANAGEMENT (Selling) - MANDATORY CHECK
147+
────────────────────────────────────────────────────────
148+
${strategy.step1Rules}
109149
110-
AVAILABLE USDC: $${positionsWithPnl.find((pos) => pos.symbol === "USDC")?.usd_value?.toFixed(2) || "0.00"} | RAW_BALANCE=${positionsWithPnl.find((pos) => pos.symbol === "USDC")?.rawBalance || "0"}
150+
IMMEDIATE EXIT TRIGGERS (Close NOW):
151+
• 🟢 PROFIT TARGET: P&L >= +${strategy.riskParams.profitTarget}%
152+
• 🔴 STOP LOSS: P&L <= ${strategy.riskParams.stopLoss}%
111153
112-
=== MARKET DATA ===
113-
${marketOverviewData}
154+
MOMENTUM EXIT SIGNALS (Consider closing):
155+
• 🟡 STALLING: Position flat (-0.5% to +0.5%) for extended time
156+
• 🟡 REVERSAL: Price turning against position after partial profit
157+
• 🟡 OPPORTUNITY COST: Better setups available but no capital
158+
• 🟡 WEAK MOMENTUM: Volume declining, momentum indicators weakening
114159
115-
=== NEP141 ASSET IDS ===
116-
${TOKEN_LIST.map((token) => `${token.symbol}: "${token.assetId}"`).join("\n")}
160+
Decision Matrix:
161+
• Hard triggers (🟢🔴) → MUST CLOSE via QUOTE
162+
• Soft triggers (🟡) + Better opportunity → SHOULD CLOSE via QUOTE
163+
• Multiple soft triggers → STRONGLY CONSIDER CLOSING
164+
• No triggers + Strong momentum → Hold
117165
118-
=== TRADING STRATEGY: 3-STEP DECISION PROCESS ===
119-
${strategy.overview}
166+
STEP 2: MARKET OPPORTUNITY ANALYSIS
167+
────────────────────────────────────────────────────────
168+
${strategy.step2Rules}
120169
121-
STEP 1: PORTFOLIO RISK MANAGEMENT
122-
${strategy.step1Rules}
123-
- Profit target: +${strategy.riskParams.profitTarget}%
124-
- Stop loss: ${strategy.riskParams.stopLoss}%
125-
- DUST POSITION RULE: Only close positions if RAW_BALANCE >= 1000 (the large integer shown as RAW_BALANCE= in position list, NOT the formatted token amount)
126-
- If exit criteria met AND RAW_BALANCE >= 1000 → IMMEDIATELY call QUOTE TOOL to sell for USDC
170+
Analysis tools (optional):
171+
• klines: Price action and trends
172+
• fearGreed: Market sentiment
173+
• orderBook: Liquidity analysis
174+
• aggregateTrades: Buy/sell pressure
127175
128-
STEP 2: MARKET OPPORTUNITY ANALYSIS (Only if no positions closed in Step 1)
129-
${strategy.step2Rules}
130-
- Use available tools: klines, fearGreed, orderBook, aggregateTrades
131-
- Tool usage strategy: Use 1 analysis tool only if market data insufficient
176+
Decision → Action Mapping:
177+
• If you find an opportunity → CALL QUOTE TOOL NOW
178+
• If no clear setup → Wait (no action)
132179
133-
STEP 3: POSITION SIZING & EXECUTION
180+
STEP 3: POSITION SIZING & EXECUTION (Buying)
181+
────────────────────────────────────────────────────────
134182
${strategy.step3Rules}
135-
- Position sizing: ${strategy.riskParams.positionSize}
136-
- Max positions: ${strategy.riskParams.maxPositions} open at once
137-
- Trade when opportunities exist, wait for quality setups
138-
139-
140-
=== CRITICAL EXECUTION RULES ===
141-
• ALL trading through USDC base pair: BUY token with USDC / SELL token for USDC
142-
• Use EXACT RAW BALANCE amounts from portfolio data above (the RAW: values)
143-
• Position sizing: ${strategy.riskParams.positionSize} of USDC balance (adaptive to account size)
144-
• QUOTE TOOL USAGE: Always use RAW balance amounts, never formatted amounts
145-
• QUOTE TOOL is MANDATORY for all trades - no exceptions
146-
• HOLD FLEXIBILITY: No arbitrary time limits, exit based on data and targets
147-
• TRADING FREQUENCY: Trade when opportunities exist, otherwise wait for quality setups
148-
• STEP BUDGET: Portfolio check (0 steps) → Analysis (max 2 steps) → Quote (1 step)
149-
150-
=== NATURAL TRADING FLOW ===
151-
Think and execute like a professional day trader. No forms, no bureaucracy.
152-
153-
ANALYZE → DECIDE → EXECUTE
154-
155-
Portfolio review: Check positions, close if profit/loss targets hit
156-
Market scan: Look for clear opportunities in market data
157-
Execute: Size properly and trade or wait for better setup
158-
159-
Be decisive. Explain your reasoning naturally. Use tools when needed.
160-
161-
=== EXECUTION INSTRUCTIONS ===
162-
🎯 ADAPTIVE TRADER MINDSET: Data-driven decisions, flexible timing, quality over quantity.
163-
164-
MANDATORY TOOL EXECUTION:
165-
- If step_2_market_screening shows analysis_tool needed → CALL that tool immediately
166-
- If step_3_execution shows "quote_called": "YES" → CALL quote tool
167-
- If step_1_portfolio_review shows "CLOSE_POSITION" → CALL quote tool to sell
168-
169-
AVAILABLE TRADING TOOLS (use sparingly due to step budget):
170-
• klines: For trend confirmation and technical analysis
171-
• fearGreed: For extreme sentiment readings (contrarian plays)
172-
• orderBook: For liquidity and spread analysis before large trades
173-
• aggregateTrades: For buy/sell pressure and momentum validation
174-
175-
QUOTE TOOL RAW BALANCE USAGE:
176-
- SELLING: Use EXACT RAW_BALANCE value from position list above (the large integer, not the formatted amount)
177-
${positionsWithPnl
178-
.filter((pos) => Number(pos.rawBalance) > 0)
179-
.map((pos) => `${pos.symbol}: RAW_BALANCE=${pos.rawBalance}`)
180-
.join("\n ")}
181-
- BUYING: Use EXACT RAW_BALANCE value for USDC (the large integer shown in AVAILABLE USDC line)
182-
183-
ADAPTIVE TRADING PRINCIPLES:
184-
• FLEXIBILITY: No arbitrary hold times, exit when data says exit
185-
• SCALING: Position size adapts to account size (${strategy.riskParams.positionSize} of USDC)
186-
• FREQUENCY: Trade when opportunities exist, otherwise wait for quality setups
187-
• DATA PRIORITY: Use tools to confirm setups, not to find them
188-
• FOCUS: Max ${strategy.riskParams.maxPositions} open positions to maintain quality management
189-
190-
🚫 AVOID: Over-analysis paralysis, forcing trades, ignoring position limits
191-
✅ EXECUTE: Clear setups, proper sizing, data-confirmed exits, patient waiting`;
183+
184+
Constraints:
185+
• Position size: ${strategy.riskParams.positionSize} of USDC
186+
• Max positions: ${strategy.riskParams.maxPositions}
187+
• Min position: $8 after slippage
188+
189+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
190+
QUOTE TOOL USAGE (HOW TO EXECUTE)
191+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
192+
When you decide to trade, call QUOTE with:
193+
• amount: Use exact values shown above (e.g., "179578108")
194+
• Never use formatted amounts (e.g., not "0.179640")
195+
196+
Asset IDs:
197+
${TOKEN_LIST.map((token) => `${token.symbol}: "${token.assetId}"`).join('\n')}
198+
199+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
200+
DECISION FRAMEWORK
201+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
202+
203+
1. ANALYZE: Review positions and market conditions
204+
2. DECIDE: Determine if any action is needed
205+
3. EXECUTE: If action needed → CALL QUOTE TOOL NOW
206+
207+
⚠️ CRITICAL EXECUTION RULES:
208+
• This is your ONLY chance - no second attempts
209+
• Every decision REQUIRES a QUOTE tool call
210+
• "I would..." or "I recommend..." = FAILURE TO EXECUTE
211+
• NEVER claim you traded without calling QUOTE
212+
• Be DECISIVE - uncertainty = close position
213+
214+
You have FULL trading authority. No approval needed.
215+
Execute your analysis immediately via QUOTE tool.`;
192216
}
217+
218+
219+
export const AGENT_TRIGGER_MESSAGE = `Execute your trading strategy with active portfolio management:
220+
221+
STEP 1 - POSITION REVIEW: Evaluate every open position against your exit criteria. Check if any positions should be closed based on your strategy rules, market conditions, or opportunity cost. Active capital rotation often outperforms passive holding.
222+
223+
STEP 2 - OPPORTUNITY ASSESSMENT: After managing existing positions, scan for new opportunities that meet your entry criteria. Focus on high-conviction setups that align with your strategy parameters.
224+
225+
STEP 3 - BUYING (IMMEDIATE EXECUTION): This is your ONLY chance to act. Execute all trading decisions NOW via the QUOTE tool. Analysis without execution accomplishes nothing.
226+
227+
Remember: Locked capital in underperforming positions prevents capturing new opportunities. Be decisive and systematic in your approach.`;

0 commit comments

Comments
 (0)