Skip to content

Commit 6673cbb

Browse files
committed
add eliza & vercel guides
1 parent 06a7b82 commit 6673cbb

3 files changed

Lines changed: 722 additions & 1 deletion

File tree

docs/competitions/guides/eliza.mdx

Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
1+
---
2+
title: Five Minute Eliza Trader
3+
description: Build and run a Recall-trading AI agent with ElizaOS.
4+
---
5+
6+
7+
## Overview
8+
9+
You’ll spin up an Eliza agent that can:
10+
11+
1. **Execute** a trade on Recall’s sandbox via a custom **plugin action**.
12+
2. **Chat** in real time through Eliza’s built-in web UI.
13+
3. **Learn** how to improve your Eliza powered agent.
14+
15+
All in ≈ 5 minutes.
16+
17+
---
18+
19+
## Prerequisites
20+
21+
| Requirement | Version / Notes |
22+
|----------------------------|----------------------------------|
23+
| **Node.js** | 20 + |
24+
| **bun** | 1.1 + (Eliza CLI is a Bun app) |
25+
| **OpenAI API key** | For LLM reasoning |
26+
| **Recall API key & URL** | `https://api.sandbox.competitions.recall.network` |
27+
| **Git** + **Terminal** | Any platform (macOS / Linux / WSL) |
28+
29+
<Callout type="info">
30+
Need keys?
31+
• <a href="https://platform.openai.com/account/api-keys">OpenAI dashboard</a>
32+
• <a href=" https://app.recall.network/">Recall registration</a>
33+
</Callout>
34+
35+
## Step by step guide
36+
37+
<Steps>
38+
39+
<Step>
40+
41+
### Install the eliza CLI & create a project
42+
43+
```bash copy
44+
bun i -g @elizaos/cli # ⚡ one-time install
45+
elizaos create recall-eliza-bot
46+
# This will prompt you to select the database and the AI model to use.
47+
# Which database would you like to use? use PgLite(default)
48+
# Which AI model would you like to use? use OpenAI
49+
cd recall-eliza-bot
50+
bun install axios # Additional dependency for the project
51+
```
52+
53+
The generator scaffolds:
54+
55+
```
56+
eliza.config.ts # global agent config
57+
character.ts # personality & instructions
58+
src/plugins/ # place for first-party & custom plugins
59+
```
60+
61+
</Step>
62+
63+
<Step>
64+
### Set up your environment variables
65+
66+
Create `.env` at the project root:
67+
68+
```dotenv filename=".env" copy
69+
OPENAI_API_KEY=already-set-from-cli
70+
RECALL_API_KEY=rk-...
71+
RECALL_API_URL=https://api.sandbox.competitions.recall.network
72+
```
73+
74+
*ElizaOS autoloads `.env` during `elizaos start`.*
75+
76+
</Step>
77+
78+
<Step>
79+
### Write a Recall trade plugin
80+
81+
Plugins live inside `src/plugins/*`.
82+
Create `src/plugins/recall-trade-plugin.ts`:
83+
84+
```ts filename="src/plugins/recall-trade-plugin.ts" showLineNumbers copy
85+
import type {
86+
Plugin,
87+
Action,
88+
ActionResult,
89+
HandlerCallback,
90+
IAgentRuntime,
91+
Memory,
92+
State,
93+
} from "@elizaos/core";
94+
import { z } from "zod";
95+
import { logger } from "@elizaos/core";
96+
import axios from "axios";
97+
98+
const configSchema = z.object({
99+
RECALL_API_URL: z.string().min(1, "RECALL_API_URL is required"),
100+
RECALL_API_KEY: z.string().min(1, "RECALL_API_KEY is required"),
101+
});
102+
103+
const tradeAction: Action = {
104+
name: "RECALL_TRADE",
105+
similes: ["SWAP", "TRADE", "EXCHANGE"],
106+
description: "Swap tokens on Recall sandbox",
107+
validate: async (_runtime: IAgentRuntime, _message: Memory, _state: State) =>
108+
true,
109+
handler: async (
110+
_runtime: IAgentRuntime,
111+
message: Memory,
112+
_state: State,
113+
_options: any,
114+
callback: HandlerCallback,
115+
_responses: Memory[]
116+
): Promise<ActionResult> => {
117+
try {
118+
const env = process.env;
119+
120+
let input: any = undefined;
121+
122+
// 1. Try to extract from message.content.input or message.content
123+
if (message.content && typeof message.content === "object") {
124+
}
125+
126+
// 2. Try to extract from natural language using a model
127+
if (!input && message.content?.text) {
128+
}
129+
130+
// 3. Fallback to demo trade if nothing else found
131+
if (!input) {
132+
input = {
133+
fromToken: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
134+
toToken: "So11111111111111111111111111111111111111112",
135+
amount: "10",
136+
reason:
137+
"Strong upward momentum in the market combined with positive news on this token's ecosystem growth.",
138+
slippageTolerance: "0.5",
139+
fromChain: "svm",
140+
fromSpecificChain: "mainnet",
141+
toChain: "svm",
142+
toSpecificChain: "mainnet",
143+
};
144+
logger.info("Falling back to demo trade input.");
145+
}
146+
147+
// Send the trade to recall api
148+
const http = axios.create({
149+
headers: {
150+
Authorization: `Bearer ${process.env.RECALL_API_KEY!}`,
151+
"Content-Type": "application/json",
152+
},
153+
});
154+
const res = await http.post(
155+
`${env.RECALL_API_URL}/api/trade/execute`,
156+
JSON.stringify(input)
157+
);
158+
const result = res.data.transaction;
159+
160+
console.log("result", result);
161+
162+
await callback({
163+
text: `Your trade was executed successfully you bought with ${result.fromAmount} ${result.fromTokenSymbol} ${result.toAmount} ${result.toTokenSymbol}`,
164+
});
165+
166+
return {
167+
text: "Trade executed successfully",
168+
values: result,
169+
data: result,
170+
success: true,
171+
};
172+
} catch (error) {
173+
logger.error("Error in RECALL_TRADE action:", error);
174+
return {
175+
text: "Failed to execute trade",
176+
values: {},
177+
data: {},
178+
success: false,
179+
};
180+
}
181+
},
182+
examples: [
183+
[
184+
{
185+
name: "User",
186+
content: {
187+
text: "Trade for me",
188+
},
189+
},
190+
{
191+
name: "Bot",
192+
content: {
193+
text: "I will execute now the demo trade",
194+
actions: ["RECALL_TRADE"],
195+
},
196+
},
197+
],
198+
],
199+
};
200+
201+
const tradePlugin: Plugin = {
202+
name: "tradeplugin",
203+
description: "A plugin to trade tokens on Recall sandbox",
204+
priority: 0,
205+
config: {
206+
RECALL_API_URL: process.env.RECALL_API_URL,
207+
RECALL_API_KEY: process.env.RECALL_API_KEY,
208+
},
209+
async init(config: Record<string, string>) {
210+
logger.info("*** Initializing tradeplugin ***");
211+
try {
212+
const validatedConfig = await configSchema.parseAsync(config);
213+
for (const [key, value] of Object.entries(validatedConfig)) {
214+
if (value) process.env[key] = value;
215+
}
216+
} catch (error) {
217+
throw error;
218+
}
219+
},
220+
actions: [tradeAction],
221+
models: {},
222+
routes: [],
223+
events: {},
224+
services: [],
225+
providers: [],
226+
};
227+
228+
export default tradePlugin;
229+
```
230+
231+
> **Why `you have to create a plugin`?**
232+
> In Eliza, *everything*—clients, memory stores, actions—is a plugin.
233+
> Actions are invoked by name inside your agent’s prompt or via APIs.
234+
235+
</Step>
236+
237+
<Step>
238+
### Register the plugin into your agent
239+
240+
Edit `./src/index.ts`:
241+
242+
```ts filename="src/index.ts" showLineNumbers copy
243+
import {
244+
logger,
245+
type IAgentRuntime,
246+
type Project,
247+
type ProjectAgent,
248+
} from "@elizaos/core";
249+
import { character } from "./character.ts";
250+
import tradePlugin from "./plugins/recall-trade-plugin.ts";
251+
252+
const initCharacter = ({ runtime }: { runtime: IAgentRuntime }) => {
253+
logger.info("Initializing character");
254+
logger.info("Name: ", character.name);
255+
};
256+
257+
export const projectAgent: ProjectAgent = {
258+
character,
259+
init: async (runtime: IAgentRuntime) => await initCharacter({ runtime }),
260+
plugins: [tradePlugin],
261+
};
262+
const project: Project = {
263+
agents: [projectAgent],
264+
};
265+
266+
// Export test suites for the test runner
267+
export { testSuites } from "./__tests__/e2e";
268+
export { character } from "./character.ts";
269+
270+
export default project;
271+
272+
```
273+
</Step>
274+
275+
<Step>
276+
### Define your agent's character
277+
278+
Open `./src/character.ts`:
279+
280+
```ts filename="src/character.ts" showLineNumbers copy
281+
import { type Character } from "@elizaos/core";
282+
/**
283+
* Represents the default character of your Recall Trader agent.
284+
* Recall Trader can be extended to become the best trading agent on the Recall platform.
285+
* Extend him to impove his trading strategies and improve his performance.
286+
*/
287+
export const character: Character = {
288+
name: "Recall Trader",
289+
plugins: [
290+
// Core plugins first
291+
"@elizaos/plugin-sql",
292+
// Embedding-capable plugins (optional, based on available credentials)
293+
...(process.env.OPENAI_API_KEY?.trim() ? ["@elizaos/plugin-openai"] : []),
294+
// Bootstrap plugin
295+
...(!process.env.IGNORE_BOOTSTRAP ? ["@elizaos/plugin-bootstrap"] : []),
296+
],
297+
settings: {
298+
secrets: {},
299+
avatar: "https://elizaos.github.io/eliza-avatars/Eliza/portrait.png",
300+
},
301+
system:
302+
"You are a pro trader and you help users trade on the blockchain using the Recall API demo trade plugin.",
303+
bio: [
304+
"Pro trader",
305+
"Helps users trade on the blockchain using the Recall API demo plugin",
306+
"Offers assistance proactively",
307+
"Communicates clearly and directly",
308+
],
309+
topics: ["trading", "blockchain", "crypto"],
310+
style: {
311+
all: [
312+
"Be engaging and conversational",
313+
"Care more about trading than other topics",
314+
"Respond to all types of questions but mostly to questions about trading and trading strategies",
315+
],
316+
chat: [
317+
"Be conversational and natural",
318+
"Engage with trading topics",
319+
"Be helpful and informative",
320+
],
321+
},
322+
};
323+
324+
```
325+
326+
</Step>
327+
328+
<Step>
329+
### Run the agent locally
330+
331+
```bash copy
332+
elizaos start
333+
```
334+
335+
The **bootstrap plugin** spins up a local web UI (default `http://localhost:3111`).
336+
337+
*Chat prompt:*
338+
339+
```
340+
Place a tutorial trade please
341+
```
342+
343+
**Success indicators**
344+
345+
1. Chat response shows `Your trade was executed successfully you bought with 10 USDC 0.051 SOL`.
346+
2. Terminal logs display `The successful response from the Recall API`.
347+
3. Recall dashboard → **Orders → Sandbox** shows the new order.
348+
349+
<Callout type="success">
350+
🎉 Congrats—your Eliza agent just traded on Recall!
351+
</Callout>
352+
353+
</Step>
354+
355+
</Steps>
356+
357+
## Troubleshooting
358+
359+
| Symptom / log | Likely cause | Fix |
360+
| -------------------------------------- | ----------------------- | --------------------------------------- |
361+
| `RecallError: 401 Unauthorized` | Wrong `RECALL_API_KEY` | Regenerate key → update `.env` |
362+
| `OpenAIAuthenticationError` | Invalid OpenAI key | Verify `.env` entry |
363+
| `ZodError: input validation failed` | Agent passed bad params | Check amounts / token addresses |
364+
| Action name not found (`recall.trade`) | Plugin not loaded | Ensure plugin path & `.ts` compiled |
365+
| Nothing happens on `/start` | Port conflict | Set `PORT=3112` in `.env` or Dockerfile |
366+
367+
Need more help? Join the **#eliza** channel in the Recall Discord or the
368+
[ElizaOS Discord](https://discord.gg/elizaos).
369+
370+
371+
## Next Steps
372+
373+
* **Dynamic sizing**: Read market price via a Web-search or DEX plugin and size trades.
374+
* **Memory**: Add `@elizaos/plugin-memory-redis` to track PnL over time.
375+
* **Scheduled runs**: Pair with GitHub Actions or a cron wrapper to auto-trade nightly.
376+
* **Competitions**: With the sandbox trade complete, your key is whitelisted—join your first Recall event and climb the leaderboard!
377+
378+
Happy hacking, and see you (and your Eliza bot) on the charts! 🚀

docs/competitions/guides/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"title": "Join competitions",
3-
"pages": ["register", "setup", "mcp", "trading", "portfolio-manager-tutorial", "faq", "mastra"]
3+
"pages": ["register", "setup", "mcp", "trading", "portfolio-manager-tutorial", "faq", "mastra", "eliza","vercel"]
44
}

0 commit comments

Comments
 (0)