@exagent/agent 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,54 @@
1
+ import {
2
+ AgentConfigSchema,
3
+ AgentRuntime,
4
+ AnthropicAdapter,
5
+ BaseLLMAdapter,
6
+ LLMConfigSchema,
7
+ LLMProviderSchema,
8
+ MarketDataService,
9
+ OllamaAdapter,
10
+ OpenAIAdapter,
11
+ RiskManager,
12
+ RiskUniverseSchema,
13
+ STRATEGY_TEMPLATES,
14
+ TradeExecutor,
15
+ TradingConfigSchema,
16
+ VaultConfigSchema,
17
+ VaultManager,
18
+ VaultPolicySchema,
19
+ createLLMAdapter,
20
+ createSampleConfig,
21
+ getAllStrategyTemplates,
22
+ getStrategyTemplate,
23
+ loadConfig,
24
+ loadStrategy,
25
+ validateConfig,
26
+ validateStrategy
27
+ } from "./chunk-JS7RJORF.mjs";
28
+ export {
29
+ AgentConfigSchema,
30
+ AgentRuntime,
31
+ AnthropicAdapter,
32
+ BaseLLMAdapter,
33
+ LLMConfigSchema,
34
+ LLMProviderSchema,
35
+ MarketDataService,
36
+ OllamaAdapter,
37
+ OpenAIAdapter,
38
+ RiskManager,
39
+ RiskUniverseSchema,
40
+ STRATEGY_TEMPLATES,
41
+ TradeExecutor,
42
+ TradingConfigSchema,
43
+ VaultConfigSchema,
44
+ VaultManager,
45
+ VaultPolicySchema,
46
+ createLLMAdapter,
47
+ createSampleConfig,
48
+ getAllStrategyTemplates,
49
+ getStrategyTemplate,
50
+ loadConfig,
51
+ loadStrategy,
52
+ validateConfig,
53
+ validateStrategy
54
+ };
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@exagent/agent",
3
+ "version": "0.1.0",
4
+ "description": "Autonomous trading agent runtime for Exagent",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "exagent": "./dist/cli.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "templates"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsup src/index.ts src/cli.ts --format cjs,esm --dts",
24
+ "dev": "tsup src/index.ts src/cli.ts --format cjs,esm --dts --watch",
25
+ "start": "node dist/cli.js",
26
+ "test": "vitest",
27
+ "lint": "eslint src/",
28
+ "clean": "rm -rf dist"
29
+ },
30
+ "dependencies": {
31
+ "@exagent/sdk": "workspace:*",
32
+ "chalk": "^5.3.0",
33
+ "commander": "^12.0.0",
34
+ "dotenv": "^16.4.0",
35
+ "openai": "^4.0.0",
36
+ "tsx": "^4.7.0",
37
+ "viem": "^2.21.0",
38
+ "zod": "^3.22.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^20.0.0",
42
+ "tsup": "^8.0.0",
43
+ "typescript": "^5.3.0",
44
+ "vitest": "^2.0.0"
45
+ },
46
+ "peerDependencies": {
47
+ "viem": "^2.0.0"
48
+ },
49
+ "engines": {
50
+ "node": ">=18.0.0"
51
+ }
52
+ }
@@ -0,0 +1,55 @@
1
+ # Exagent Agent Configuration
2
+ # WARNING: Never commit this file to version control!
3
+ # Keep your private key and API keys secret.
4
+
5
+ # ============================================
6
+ # REQUIRED: Your wallet private key
7
+ # ============================================
8
+ # This wallet will be used to:
9
+ # 1. Link to your agent identity on-chain
10
+ # 2. Execute trades through the ExagentRouter
11
+ # 3. Pay gas fees for transactions
12
+ #
13
+ # Format: 64 hex characters starting with 0x
14
+ # Example: 0x1234567890abcdef...
15
+ EXAGENT_PRIVATE_KEY=
16
+
17
+ # ============================================
18
+ # REQUIRED: Network (mainnet or testnet)
19
+ # ============================================
20
+ # Use 'testnet' for Base Sepolia (recommended for testing)
21
+ # Use 'mainnet' for Base mainnet (real money!)
22
+ EXAGENT_NETWORK=testnet
23
+
24
+ # ============================================
25
+ # LLM API Keys (choose one based on your config)
26
+ # ============================================
27
+
28
+ # OpenAI API Key
29
+ # Get yours at: https://platform.openai.com/api-keys
30
+ # OPENAI_API_KEY=sk-...
31
+
32
+ # Anthropic API Key
33
+ # Get yours at: https://console.anthropic.com/settings/keys
34
+ # ANTHROPIC_API_KEY=sk-ant-...
35
+
36
+ # Ollama (Local LLM - no API key needed)
37
+ # Just install Ollama: https://ollama.com/download
38
+ # Then run: ollama serve
39
+ # And pull your model: ollama pull mistral
40
+ # EXAGENT_LLM_URL=http://localhost:11434
41
+
42
+ # ============================================
43
+ # Optional: Override LLM model
44
+ # ============================================
45
+ # EXAGENT_LLM_MODEL=gpt-4-turbo-preview
46
+
47
+ # ============================================
48
+ # Optional: Custom config path
49
+ # ============================================
50
+ # EXAGENT_CONFIG=./agent-config.json
51
+
52
+ # ============================================
53
+ # Optional: Custom strategy path
54
+ # ============================================
55
+ # EXAGENT_STRATEGY=./strategy.ts
@@ -0,0 +1,60 @@
1
+ # Docker Compose for Exagent Trading Agent
2
+ #
3
+ # Usage:
4
+ # 1. Copy .env.template to .env and fill in your secrets
5
+ # 2. Run: docker-compose up -d
6
+ # 3. View logs: docker-compose logs -f
7
+ # 4. Stop: docker-compose down
8
+
9
+ version: '3.8'
10
+
11
+ services:
12
+ agent:
13
+ image: node:20-alpine
14
+ container_name: exagent-${AGENT_NAME:-agent}
15
+ working_dir: /app
16
+ volumes:
17
+ - .:/app
18
+ - agent_node_modules:/app/node_modules
19
+ environment:
20
+ - NODE_ENV=production
21
+ - EXAGENT_PRIVATE_KEY=${EXAGENT_PRIVATE_KEY}
22
+ - EXAGENT_NETWORK=${EXAGENT_NETWORK:-testnet}
23
+ - OPENAI_API_KEY=${OPENAI_API_KEY:-}
24
+ - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
25
+ - EXAGENT_LLM_URL=${EXAGENT_LLM_URL:-}
26
+ command: npm start
27
+ restart: unless-stopped
28
+ healthcheck:
29
+ test: ["CMD", "node", "-e", "console.log('healthy')"]
30
+ interval: 30s
31
+ timeout: 10s
32
+ retries: 3
33
+ logging:
34
+ driver: "json-file"
35
+ options:
36
+ max-size: "10m"
37
+ max-file: "3"
38
+
39
+ # Optional: Local Ollama for on-device LLM
40
+ # Uncomment if using local LLM
41
+ #
42
+ # ollama:
43
+ # image: ollama/ollama
44
+ # container_name: exagent-ollama
45
+ # volumes:
46
+ # - ollama_models:/root/.ollama
47
+ # ports:
48
+ # - "11434:11434"
49
+ # deploy:
50
+ # resources:
51
+ # reservations:
52
+ # devices:
53
+ # - driver: nvidia
54
+ # count: all
55
+ # capabilities: [gpu]
56
+ # restart: unless-stopped
57
+
58
+ volumes:
59
+ agent_node_modules:
60
+ # ollama_models: # Uncomment if using Ollama
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Custom Trading Strategy
3
+ *
4
+ * This is YOUR strategy file - customize it to your needs.
5
+ * Your prompts and logic are your competitive advantage.
6
+ * We don't store or know what's in this file.
7
+ *
8
+ * IMPORTANT WARNINGS:
9
+ * - LLMs can hallucinate or make errors. Always validate outputs.
10
+ * - Test thoroughly on testnet before using real funds.
11
+ * - Agents may not behave exactly as expected based on your prompts.
12
+ * - You are fully responsible for your trading decisions.
13
+ */
14
+
15
+ import type {
16
+ StrategyFunction,
17
+ MarketData,
18
+ TradeSignal,
19
+ LLMAdapter,
20
+ AgentConfig,
21
+ } from '@exagent/agent';
22
+
23
+ /**
24
+ * Your custom system prompt
25
+ *
26
+ * This is the secret sauce of your trading agent.
27
+ * Customize this to define how your agent thinks and trades.
28
+ */
29
+ const SYSTEM_PROMPT = `You are an AI trading assistant analyzing cryptocurrency markets.
30
+
31
+ Your role is to analyze market data and provide trading recommendations.
32
+
33
+ IMPORTANT CONSTRAINTS:
34
+ - Only recommend trades when you have high confidence
35
+ - Consider risk/reward ratios
36
+ - Never exceed position size limits
37
+ - Be conservative - it's okay to recommend "hold"
38
+
39
+ When analyzing market data, consider:
40
+ 1. Price trends and momentum
41
+ 2. Current portfolio allocation
42
+ 3. Risk management
43
+
44
+ Respond with JSON in this exact format:
45
+ {
46
+ "analysis": "Brief market analysis (1-2 sentences)",
47
+ "signals": [
48
+ {
49
+ "action": "buy" | "sell" | "hold",
50
+ "tokenIn": "0x...",
51
+ "tokenOut": "0x...",
52
+ "percentage": 0-100,
53
+ "confidence": 0-1,
54
+ "reasoning": "Why this trade"
55
+ }
56
+ ]
57
+ }
58
+
59
+ If you're unsure or market conditions are unclear, respond with:
60
+ {
61
+ "analysis": "Market conditions unclear",
62
+ "signals": [{ "action": "hold", "confidence": 1.0, "reasoning": "Waiting for clearer signals" }]
63
+ }`;
64
+
65
+ /**
66
+ * Generate trading signals
67
+ *
68
+ * This function is called on each trading cycle.
69
+ * It receives market data, has access to the LLM, and returns trade signals.
70
+ *
71
+ * @param marketData - Current prices, balances, and portfolio value
72
+ * @param llm - LLM adapter for analysis
73
+ * @param config - Agent configuration
74
+ * @returns Array of trade signals
75
+ */
76
+ export const generateSignals: StrategyFunction = async (
77
+ marketData: MarketData,
78
+ llm: LLMAdapter,
79
+ config: AgentConfig
80
+ ): Promise<TradeSignal[]> => {
81
+ // Format market data for the LLM
82
+ const userMessage = JSON.stringify({
83
+ timestamp: new Date(marketData.timestamp).toISOString(),
84
+ prices: marketData.prices,
85
+ portfolioValue: `$${marketData.portfolioValue.toFixed(2)}`,
86
+ balances: formatBalances(marketData.balances),
87
+ config: {
88
+ riskUniverse: config.riskUniverse,
89
+ maxPositionSize: `${config.trading.maxPositionSizeBps / 100}%`,
90
+ timeHorizon: config.trading.timeHorizon,
91
+ },
92
+ }, null, 2);
93
+
94
+ // Call the LLM
95
+ const response = await llm.chat([
96
+ { role: 'system', content: SYSTEM_PROMPT },
97
+ { role: 'user', content: userMessage },
98
+ ]);
99
+
100
+ // Parse and validate the response
101
+ try {
102
+ const parsed = JSON.parse(response.content);
103
+
104
+ if (!parsed.signals || !Array.isArray(parsed.signals)) {
105
+ console.warn('LLM response missing signals array');
106
+ return [];
107
+ }
108
+
109
+ // Log analysis
110
+ if (parsed.analysis) {
111
+ console.log(`Analysis: ${parsed.analysis}`);
112
+ }
113
+
114
+ // Convert to TradeSignal format
115
+ return parsed.signals
116
+ .filter((s: any) => s.action !== 'hold') // Filter out hold signals
117
+ .map((s: any) => ({
118
+ action: s.action as 'buy' | 'sell',
119
+ tokenIn: s.tokenIn || '',
120
+ tokenOut: s.tokenOut || '',
121
+ amountIn: calculateAmount(s.percentage, marketData),
122
+ confidence: s.confidence || 0.5,
123
+ reasoning: s.reasoning,
124
+ }));
125
+ } catch (error) {
126
+ console.error('Failed to parse LLM response:', error);
127
+ console.error('Raw response:', response.content);
128
+ return []; // Safe fallback: no trades
129
+ }
130
+ };
131
+
132
+ /**
133
+ * Format balances for LLM display
134
+ */
135
+ function formatBalances(balances: Record<string, bigint>): Record<string, string> {
136
+ const formatted: Record<string, string> = {};
137
+ for (const [address, balance] of Object.entries(balances)) {
138
+ // Assume 18 decimals for simplicity
139
+ const amount = Number(balance) / 1e18;
140
+ formatted[address] = amount.toFixed(6);
141
+ }
142
+ return formatted;
143
+ }
144
+
145
+ /**
146
+ * Calculate trade amount from percentage
147
+ */
148
+ function calculateAmount(percentage: number, marketData: MarketData): bigint {
149
+ // This is a simplified calculation
150
+ // In production, you'd want to calculate based on actual token balances
151
+ const value = (marketData.portfolioValue * percentage) / 100;
152
+ return BigInt(Math.floor(value * 1e18));
153
+ }