-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathagent.js
More file actions
155 lines (129 loc) · 5.17 KB
/
Copy pathagent.js
File metadata and controls
155 lines (129 loc) · 5.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import Groq from 'groq-sdk'
import { tools } from './tools.js'
import { executeTool } from './executor.js'
import readline from 'readline'
// ─── Init ─────────────────────────────────────────────────────────────────────
const groq = new Groq({ apiKey: process.env.GROQ_API_KEY })
const MODEL = 'llama-3.3-70b-versatile'
const SYSTEM = `You are ChainAgent — an autonomous AI agent that executes on-chain actions.
You have access to these tools:
- wallet_balance: check USDC/AVAX balance
- send_avax: send AVAX to an address via direct transfer
- mint_nft: mint an NFT to an address via smart contract
- deploy_contract: deploy escrow/NFT contract (requires USDC payment)
- lock_bounty: lock USDC into escrow contract
- release_bounty: release escrowed USDC to a recipient
- list_facilitators: list the available facilitators/participants
Rules:
- Always plan your steps before executing
- Show the user each step as you go
- For actions that cost money, confirm with the user first
- If an action returns a txHash, always show it
- Be concise. You are a terminal agent, not a chatbot.`
// ─── Convert Anthropic tool schema → Groq/OpenAI tool schema ─────────────────
function toGroqTools(tools) {
return tools.map(t => ({
type: 'function',
function: {
name: t.name,
description: t.description,
parameters: t.input_schema,
},
}))
}
// ─── Agent loop ───────────────────────────────────────────────────────────────
async function runAgent(userMessage) {
const messages = [
{ role: 'system', content: SYSTEM },
{ role: 'user', content: userMessage },
]
console.log('\n🤖 ChainAgent thinking...\n')
while (true) {
let response
try {
response = await groq.chat.completions.create({
model: MODEL,
max_tokens: 4096,
tools: toGroqTools(tools),
tool_choice: 'auto',
messages,
})
} catch (err) {
// Groq API errors (BadRequestError, rate limits, etc.) — don't crash
const detail = err?.error?.error?.failed_generation || err?.error?.error?.message || err.message
console.log(`\n❌ AI Error: ${detail}\n`)
break
}
const msg = response.choices[0].message
const finishReason = response.choices[0].finish_reason
// Print any text the agent says
if (msg.content) {
console.log(msg.content)
}
// If agent is done, break
if (finishReason === 'stop') break
// If agent wants to use tools
if (finishReason === 'tool_calls' && msg.tool_calls?.length) {
// Add assistant message with tool calls to history
messages.push(msg)
for (const toolCall of msg.tool_calls) {
const toolName = toolCall.function.name
let toolInput
try {
toolInput = JSON.parse(toolCall.function.arguments)
} catch {
console.log(`⚠️ Could not parse arguments for ${toolName}, skipping.`)
continue
}
console.log(`\n⚡ Executing: ${toolName}`)
console.log(` Input: ${JSON.stringify(toolInput, null, 2)}`)
const result = await executeTool(toolName, toolInput)
console.log(` Result: ${JSON.stringify(result, null, 2)}\n`)
// Feed each tool result back
messages.push({
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(result),
})
}
} else if (finishReason !== 'stop') {
// Unexpected finish reason — bail safely
break
}
}
}
// ─── CLI ──────────────────────────────────────────────────────────────────────
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
})
console.log('╔══════════════════════════════════════╗')
console.log('║ ChainAgent — On-Chain AI Agent ║')
console.log('║ Network: avalanche-fuji (AVAX) ║')
console.log('║ Powered by Groq Llama-3.3-70b ║')
console.log('╚══════════════════════════════════════╝')
console.log('\nCommands you can try:')
console.log(' → wallet balance')
console.log(' → send 0.01 AVAX to 0xAbc...')
console.log(' → mint nft "Vibeathon Winner" to 0xAbc...')
console.log(' → lock bounty 1 USDC')
console.log(' → list facilitators')
console.log(' → deploy contract\n')
function prompt() {
rl.question('you > ', async (input) => {
if (input.trim().toLowerCase() === 'exit') {
console.log('Goodbye.')
rl.close()
return
}
if (input.trim()) {
try {
await runAgent(input.trim())
} catch (err) {
console.log(`\n❌ Unexpected error: ${err.message}\n`)
}
}
prompt()
})
}
prompt()