77 }),
78 execute: async ({ query }) => {
79 const apiKey = Deno.env.get("EXA_API_KEY");
80 const exa = new Exa(apiKey);
81 const result = await exa.searchAndContents(query, {
82 text: true,
100 }),
101 execute: async ({ url }) => {
102 const apiKey = Deno.env.get("EXA_API_KEY");
103 const exa = new Exa(apiKey);
104 const result = await exa.getContents([url], { text: true });
105 return {
1# Autonomous Val
2This project demonstrates how to build autonomous agents on Val Town that can be triggered by API calls, cron jobs, etc.
3
4
8
9Configure the following variables in your environment:
10- `AGENT_API_KEY` (This is a secure token that you choose to secure the agent.tsx POST endpoint)
11- `OPENAI_API_KEY` (An OpenAI API Key)
12- `EXA_API_KEY` (Optional, though needed if you use the web search tool)
13
14## Usage
15Use `demo.tsx` to send objectives to your agent.
16
17### API Usage
18To use the API from another client, you can POST authenticated requests to the agent.tsx endpoint:
19
20```javascript
30 headers: {
31 "Content-Type": "application/json",
32 "Authorization": `Bearer ${Deno.env.get("AGENT_API_KEY")}`,
33 },
34 body: JSON.stringify(requestBody),
37
38### Streaming Chat
39The API will also work with streaming chat front ends based on the Vercel AI SDK's useChat hook.
40
41You just need to pass `streamResults: true` in your API POST request.
42
43## Using Other Models
22 objective = formData.get("objective")?.toString() || objective;
23
24 // Continue with API call using the submitted objective
25 } else {
26 return new Response("Unsupported content type", { status: 415 });
27 }
28
29 // Make API call with the objective from the form
30 const requestBody = {
31 messages: [
40 headers: {
41 "Content-Type": "application/json",
42 "Authorization": `Bearer ${Deno.env.get("AGENT_API_KEY")}`,
43 },
44 body: JSON.stringify(requestBody),
50 }
51
52 // Get the API response data
53 const responseData = await response.json();
54 console.log("API Response:", responseData);
55
56 // Return HTML with the results
32});
33
34// API Routes
35app.post("/api/logs/parse", async c => {
36 try {
37 const body = await c.req.json();
55});
56
57app.get("/api/logs/sample", c => {
58 const sampleLog = `{"level":20,"time":1749687663226,"pid":1115261,"hostname":"wolf-laptop","method":"initialize","params":{"capabilities":{"textDocument":{"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"moniker":{},"synchronization":{"dynamicRegistration":true,"willSave":false,"didSave":false,"willSaveWaitUntil":false},"codeAction":{"dynamicRegistration":true,"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"resolveSupport":{"properties":["edit"]}},"completion":{"dynamicRegistration":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":true,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":false,"preselectSupport":true},"contextSupport":true},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"]}},"declaration":{"dynamicRegistration":true,"linkSupport":true},"definition":{"dynamicRegistration":true,"linkSupport":true},"typeDefinition":{"dynamicRegistration":true,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"rename":{"dynamicRegistration":true,"prepareSupport":true}},"workspace":{"didChangeConfiguration":{"dynamicRegistration":true}}}},"msg":"Received request from client"}
59{"level":20,"time":1749687663227,"pid":1115261,"hostname":"wolf-laptop","msg":"Received initialize request from client"}
60{"level":20,"time":1749687663227,"pid":1115261,"hostname":"wolf-laptop","msg":"Pre process spawn callback executed"}
61{"level":40,"time":1749687663227,"pid":1115261,"hostname":"wolf-laptop","msg":"No API key provided in LSP init options to use for Deno LSP"}
62{"level":20,"time":1749687663235,"pid":1115261,"hostname":"wolf-laptop","msg":"Debug output will be written to denolsp.log"}
63{"level":20,"time":1749687663235,"pid":1115261,"hostname":"wolf-laptop","pid":1115407,"msg":"LSP process started"}
23 setLoading(true);
24 try {
25 const response = await fetch('/api/logs/parse', {
26 method: 'POST',
27 headers: {
68 setLoading(true);
69 try {
70 const response = await fetch('/api/logs/sample');
71 const data = await response.json();
72 setLogText(data.sampleLog);
149 <pre className="text-xs text-blue-800 font-mono">
150{`{"level":20,"time":1749686800950,"pid":925732,"hostname":"wolf-laptop","method":"initialize","msg":"Received request from client"}
151{"level":40,"time":1749686800951,"pid":925732,"hostname":"wolf-laptop","msg":"No API key provided"}`}
152 </pre>
153 </div>
365 <div class="card">
366 <h3>Error Loading Suggestions</h3>
367 <p>We couldn't get AI-powered task suggestions. This can happen due to network issues or API errors.</p>
368 <div class="status-entry error">\${esc(suggestionsError)}</div>
369 <button id="retry-suggestions-btn" class="button button-primary" style="margin-top:10px;">Retry Suggestions</button>
899 }
900 } catch (error) {
901 const errMsg = `AI API Error: ${error.message}`;
902 log.push({ agent: agentName, type: "error", message: errMsg });
903 console.error(`${agentName} Error:`, error);
904 return { error: "AI_API_ERROR", message: errMsg, details: error.toString() };
905 }
906 }