Skip to content

Fix research rules handling: prevent LLM confusion and unnecessary tool cascades#262

Merged
virattt merged 2 commits into
virattt:mainfrom
swrzalek:fix-rules-command
May 11, 2026
Merged

Fix research rules handling: prevent LLM confusion and unnecessary tool cascades#262
virattt merged 2 commits into
virattt:mainfrom
swrzalek:fix-rules-command

Conversation

@swrzalek
Copy link
Copy Markdown
Contributor

@swrzalek swrzalek commented May 11, 2026

Title: Fix research rules handling: prevent LLM confusion and unnecessary tool cascades

Description:

Fixes two related issues with .dexter/RULES.md handling:

  1. LLM fails to create first research rule — The system prompt only showed "use write_file or edit_file to modify rules" when RULES.md already existed. For the first rule, the LLM never saw these instructions and fell back to memory_search (which mentions "portfolio rules") and then web_search.

  2. /rules command triggers tool cascade — The slash command routed through the full agent loop, causing the agent to call read_file, browser, memory_search, and read_file again just to discover the file didn't exist.

Changes:

  • src/agent/prompts.ts — Rule management instructions now always appear in the system prompt, not just when rules already exist
  • src/tools/filesystem/write-file.ts — Added .dexter/RULES.md as an explicit use case example
  • src/tools/filesystem/edit-file.ts — Added .dexter/RULES.md editing as an explicit use case example
  • src/tools/memory/memory-search.ts — Changed "portfolio rules" to "portfolio/trading rules" to reduce confusion with research rules
  • src/cli.ts/rules command now reads .dexter/RULES.md directly and displays results or a "no rules set" message, bypassing the agent loop entirely

Testing:

  • bun run typecheck passes
  • bun test passes (37 tests)

Logs:

Before:

Image
{"type":"init","content":"Show me my current research rules from .dexter/RULES.md","timestamp":"2026-05-11T11:27:24.639Z"}
{"type":"tool_result","timestamp":"2026-05-11T11:27:25.873Z","toolName":"read_file","args":{"path":".dexter/RULES.md"},"result":"Error: ENOENT: no such file or directory, access '/Users/user/Projects/dexter/.dexter/RULES.md'"}
{"type":"tool_result","timestamp":"2026-05-11T11:27:29.589Z","toolName":"browser","args":{"url":"file:///Users/user/Projects/dexter/.dexter/","action":"navigate"},"result":{"data":{"ok":true,"url":"file:///Users/user/Projects/dexter/.dexter/","title":"Index of /Users/user/Projects/dexter/.dexter/","hint":"Page loaded. Call snapshot to see page structure and find elements to interact with."}}}
{"type":"tool_result","timestamp":"2026-05-11T11:27:30.890Z","toolName":"browser","args":{"action":"snapshot"},"result":{"data":{"url":"file:///Users/user/Projects/dexter/.dexter/","title":"Index of /Users/user/Projects/dexter/.dexter/","snapshot":"- generic [active] [ref=e1]:\n  - heading \"Index of /Users/user/Projects/dexter/.dexter/\" [level=1] [ref=e2]\n  - link \"[parent directory]\" [ref=e4] [cursor=pointer]:\n    - /url: /Users/user/Projects/dexter/.dexter/..\n  - table [ref=e5]:\n    - rowgroup [ref=e6]:\n      - row \"Name Size Date Modified\" [ref=e7]:\n        - button \"Name\" [ref=e8] [cursor=pointer]\n        - button \"Size\" [ref=e9] [cursor=pointer]\n        - button \"Date Modified\" [ref=e10] [cursor=pointer]\n    - rowgroup [ref=e11]:\n      - row \"memory/ 5/11/26, 11:04:35 AM\" [ref=e12]:\n        - cell \"memory/\" [ref=e13]:\n          - link \"memory/\" [ref=e14] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.dexter/memory/\n        - cell [ref=e15]\n        - cell \"5/11/26, 11:04:35 AM\" [ref=e16]\n      - row \"messages/ 5/11/26, 12:22:42 AM\" [ref=e17]:\n        - cell \"messages/\" [ref=e18]:\n          - link \"messages/\" [ref=e19] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.dexter/messages/\n        - cell [ref=e20]\n        - cell \"5/11/26, 12:22:42 AM\" [ref=e21]\n      - row \"scratchpad/ 5/11/26, 12:27:24 PM\" [ref=e22]:\n        - cell \"scratchpad/\" [ref=e23]:\n          - link \"scratchpad/\" [ref=e24] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.dexter/scratchpad/\n        - cell [ref=e25]\n        - cell \"5/11/26, 12:27:24 PM\" [ref=e26]\n      - row \"settings.json 65 B 5/11/26, 12:26:49 AM\" [ref=e27]:\n        - cell \"settings.json\" [ref=e28]:\n          - link \"settings.json\" [ref=e29] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.dexter/settings.json\n        - cell \"65 B\" [ref=e30]\n        - cell \"5/11/26, 12:26:49 AM\" [ref=e31]","truncated":false,"refCount":30,"refs":{"e1":{"role":"generic"},"e2":{"role":"heading","name":"Index of /Users/user/Projects/dexter/.dexter/"},"e4":{"role":"link","name":"[parent directory]"},"e5":{"role":"table"},"e6":{"role":"rowgroup"},"e7":{"role":"row","name":"Name Size Date Modified"},"e8":{"role":"button","name":"Name"},"e9":{"role":"button","name":"Size"},"e10":{"role":"button","name":"Date Modified"},"e11":{"role":"rowgroup"},"e12":{"role":"row","name":"memory/ 5/11/26, 11:04:35 AM"},"e13":{"role":"cell","name":"memory/"},"e14":{"role":"link","name":"memory/"},"e15":{"role":"cell"},"e16":{"role":"cell","name":"5/11/26, 11:04:35 AM"},"e17":{"role":"row","name":"messages/ 5/11/26, 12:22:42 AM"},"e18":{"role":"cell","name":"messages/"},"e19":{"role":"link","name":"messages/"},"e20":{"role":"cell"},"e21":{"role":"cell","name":"5/11/26, 12:22:42 AM"},"e22":{"role":"row","name":"scratchpad/ 5/11/26, 12:27:24 PM"},"e23":{"role":"cell","name":"scratchpad/"},"e24":{"role":"link","name":"scratchpad/"},"e25":{"role":"cell"},"e26":{"role":"cell","name":"5/11/26, 12:27:24 PM"},"e27":{"role":"row","name":"settings.json 65 B 5/11/26, 12:26:49 AM"},"e28":{"role":"cell","name":"settings.json"},"e29":{"role":"link","name":"settings.json"},"e30":{"role":"cell","name":"65 B"},"e31":{"role":"cell","name":"5/11/26, 12:26:49 AM"}},"hint":"Use act with kind=\"click\" and ref=\"eN\" to click elements. Or navigate directly to a /url visible in the snapshot."}}}
{"type":"tool_result","timestamp":"2026-05-11T11:27:33.080Z","toolName":"browser","args":{"url":"file:///Users/user/Projects/dexter/","action":"navigate"},"result":{"data":{"ok":true,"url":"file:///Users/user/Projects/dexter/","title":"Index of /Users/user/Projects/dexter/","hint":"Page loaded. Call snapshot to see page structure and find elements to interact with."}}}
{"type":"tool_result","timestamp":"2026-05-11T11:27:34.684Z","toolName":"browser","args":{"action":"snapshot"},"result":{"data":{"url":"file:///Users/user/Projects/dexter/","title":"Index of /Users/user/Projects/dexter/","snapshot":"- generic [active] [ref=e1]:\n  - heading \"Index of /Users/user/Projects/dexter/\" [level=1] [ref=e2]\n  - link \"[parent directory]\" [ref=e4] [cursor=pointer]:\n    - /url: /Users/user/Projects/dexter/..\n  - table [ref=e5]:\n    - rowgroup [ref=e6]:\n      - row \"Name Size Date Modified\" [ref=e7]:\n        - button \"Name\" [ref=e8] [cursor=pointer]\n        - button \"Size\" [ref=e9] [cursor=pointer]\n        - button \"Date Modified\" [ref=e10] [cursor=pointer]\n    - rowgroup [ref=e11]:\n      - row \".dexter/ 5/11/26, 12:21:32 PM\" [ref=e12]:\n        - cell \".dexter/\" [ref=e13]:\n          - link \".dexter/\" [ref=e14] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.dexter/\n        - cell [ref=e15]\n        - cell \"5/11/26, 12:21:32 PM\" [ref=e16]\n      - row \".git/ 5/11/26, 12:27:14 PM\" [ref=e17]:\n        - cell \".git/\" [ref=e18]:\n          - link \".git/\" [ref=e19] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.git/\n        - cell [ref=e20]\n        - cell \"5/11/26, 12:27:14 PM\" [ref=e21]\n      - row \".github/ 5/11/26, 12:19:51 AM\" [ref=e22]:\n        - cell \".github/\" [ref=e23]:\n          - link \".github/\" [ref=e24] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.github/\n        - cell [ref=e25]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e26]\n      - row \"node_modules/ 5/11/26, 12:22:34 AM\" [ref=e27]:\n        - cell \"node_modules/\" [ref=e28]:\n          - link \"node_modules/\" [ref=e29] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/node_modules/\n        - cell [ref=e30]\n        - cell \"5/11/26, 12:22:34 AM\" [ref=e31]\n      - row \"scripts/ 5/11/26, 12:19:51 AM\" [ref=e32]:\n        - cell \"scripts/\" [ref=e33]:\n          - link \"scripts/\" [ref=e34] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/scripts/\n        - cell [ref=e35]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e36]\n      - row \"src/ 5/11/26, 12:17:18 PM\" [ref=e37]:\n        - cell \"src/\" [ref=e38]:\n          - link \"src/\" [ref=e39] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/src/\n        - cell [ref=e40]\n        - cell \"5/11/26, 12:17:18 PM\" [ref=e41]\n      - row \".env 1.1 kB 5/11/26, 12:23:11 AM\" [ref=e42]:\n        - cell \".env\" [ref=e43]:\n          - link \".env\" [ref=e44] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.env\n        - cell \"1.1 kB\" [ref=e45]\n        - cell \"5/11/26, 12:23:11 AM\" [ref=e46]\n      - row \".gitignore 531 B 5/11/26, 12:19:51 AM\" [ref=e47]:\n        - cell \".gitignore\" [ref=e48]:\n          - link \".gitignore\" [ref=e49] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.gitignore\n        - cell \"531 B\" [ref=e50]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e51]\n      - row \"AGENTS.md 5.4 kB 5/11/26, 12:19:51 AM\" [ref=e52]:\n        - cell \"AGENTS.md\" [ref=e53]:\n          - link \"AGENTS.md\" [ref=e54] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/AGENTS.md\n        - cell \"5.4 kB\" [ref=e55]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e56]\n      - row \"bun.lock 257 kB 5/11/26, 12:19:51 AM\" [ref=e57]:\n        - cell \"bun.lock\" [ref=e58]:\n          - link \"bun.lock\" [ref=e59] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/bun.lock\n        - cell \"257 kB\" [ref=e60]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e61]\n      - row \"env.example 1.0 kB 5/11/26, 12:19:51 AM\" [ref=e62]:\n        - cell \"env.example\" [ref=e63]:\n          - link \"env.example\" [ref=e64] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/env.example\n        - cell \"1.0 kB\" [ref=e65]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e66]\n      - row \"jest.config.js 1.2 kB 5/11/26, 12:19:51 AM\" [ref=e67]:\n        - cell \"jest.config.js\" [ref=e68]:\n          - link \"jest.config.js\" [ref=e69] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/jest.config.js\n        - cell \"1.2 kB\" [ref=e70]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e71]\n      - row \"package-lock.json 329 kB 5/11/26, 12:19:51 AM\" [ref=e72]:\n        - cell \"package-lock.json\" [ref=e73]:\n          - link \"package-lock.json\" [ref=e74] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/package-lock.json\n        - cell \"329 kB\" [ref=e75]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e76]\n      - row \"package.json 1.6 kB 5/11/26, 12:19:51 AM\" [ref=e77]:\n        - cell \"package.json\" [ref=e78]:\n          - link \"package.json\" [ref=e79] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/package.json\n        - cell \"1.6 kB\" [ref=e80]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e81]\n      - row \"README.md 6.5 kB 5/11/26, 12:19:51 AM\" [ref=e82]:\n        - cell \"README.md\" [ref=e83]:\n          - link \"README.md\" [ref=e84] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/README.md\n        - cell \"6.5 kB\" [ref=e85]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e86]\n      - row \"SOUL.md 6.9 kB 5/11/26, 12:19:51 AM\" [ref=e87]:\n        - cell \"SOUL.md\" [ref=e88]:\n          - link \"SOUL.md\" [ref=e89] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/SOUL.md\n        - cell \"6.9 kB\" [ref=e90]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e91]\n      - row \"tsconfig.json 524 B 5/11/26, 12:19:51 AM\" [ref=e92]:\n        - cell \"tsconfig.json\" [ref=e93]:\n          - link \"tsconfig.json\" [ref=e94] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/tsconfig.json\n        - cell \"524 B\" [ref=e95]\n        - cell \"5/11/26, 12:19:51 AM\" [ref=e96]","truncated":false,"refCount":95,"refs":{"e1":{"role":"generic"},"e2":{"role":"heading","name":"Index of /Users/user/Projects/dexter/"},"e4":{"role":"link","name":"[parent directory]"},"e5":{"role":"table"},"e6":{"role":"rowgroup"},"e7":{"role":"row","name":"Name Size Date Modified"},"e8":{"role":"button","name":"Name"},"e9":{"role":"button","name":"Size"},"e10":{"role":"button","name":"Date Modified"},"e11":{"role":"rowgroup"},"e12":{"role":"row","name":".dexter/ 5/11/26, 12:21:32 PM"},"e13":{"role":"cell","name":".dexter/"},"e14":{"role":"link","name":".dexter/"},"e15":{"role":"cell"},"e16":{"role":"cell","name":"5/11/26, 12:21:32 PM"},"e17":{"role":"row","name":".git/ 5/11/26, 12:27:14 PM"},"e18":{"role":"cell","name":".git/"},"e19":{"role":"link","name":".git/"},"e20":{"role":"cell"},"e21":{"role":"cell","name":"5/11/26, 12:27:14 PM"},"e22":{"role":"row","name":".github/ 5/11/26, 12:19:51 AM"},"e23":{"role":"cell","name":".github/"},"e24":{"role":"link","name":".github/"},"e25":{"role":"cell"},"e26":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e27":{"role":"row","name":"node_modules/ 5/11/26, 12:22:34 AM"},"e28":{"role":"cell","name":"node_modules/"},"e29":{"role":"link","name":"node_modules/"},"e30":{"role":"cell"},"e31":{"role":"cell","name":"5/11/26, 12:22:34 AM"},"e32":{"role":"row","name":"scripts/ 5/11/26, 12:19:51 AM"},"e33":{"role":"cell","name":"scripts/"},"e34":{"role":"link","name":"scripts/"},"e35":{"role":"cell"},"e36":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e37":{"role":"row","name":"src/ 5/11/26, 12:17:18 PM"},"e38":{"role":"cell","name":"src/"},"e39":{"role":"link","name":"src/"},"e40":{"role":"cell"},"e41":{"role":"cell","name":"5/11/26, 12:17:18 PM"},"e42":{"role":"row","name":".env 1.1 kB 5/11/26, 12:23:11 AM"},"e43":{"role":"cell","name":".env"},"e44":{"role":"link","name":".env"},"e45":{"role":"cell","name":"1.1 kB"},"e46":{"role":"cell","name":"5/11/26, 12:23:11 AM"},"e47":{"role":"row","name":".gitignore 531 B 5/11/26, 12:19:51 AM"},"e48":{"role":"cell","name":".gitignore"},"e49":{"role":"link","name":".gitignore"},"e50":{"role":"cell","name":"531 B"},"e51":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e52":{"role":"row","name":"AGENTS.md 5.4 kB 5/11/26, 12:19:51 AM"},"e53":{"role":"cell","name":"AGENTS.md"},"e54":{"role":"link","name":"AGENTS.md"},"e55":{"role":"cell","name":"5.4 kB"},"e56":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e57":{"role":"row","name":"bun.lock 257 kB 5/11/26, 12:19:51 AM"},"e58":{"role":"cell","name":"bun.lock"},"e59":{"role":"link","name":"bun.lock"},"e60":{"role":"cell","name":"257 kB"},"e61":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e62":{"role":"row","name":"env.example 1.0 kB 5/11/26, 12:19:51 AM"},"e63":{"role":"cell","name":"env.example"},"e64":{"role":"link","name":"env.example"},"e65":{"role":"cell","name":"1.0 kB"},"e66":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e67":{"role":"row","name":"jest.config.js 1.2 kB 5/11/26, 12:19:51 AM"},"e68":{"role":"cell","name":"jest.config.js"},"e69":{"role":"link","name":"jest.config.js"},"e70":{"role":"cell","name":"1.2 kB"},"e71":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e72":{"role":"row","name":"package-lock.json 329 kB 5/11/26, 12:19:51 AM"},"e73":{"role":"cell","name":"package-lock.json"},"e74":{"role":"link","name":"package-lock.json"},"e75":{"role":"cell","name":"329 kB"},"e76":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e77":{"role":"row","name":"package.json 1.6 kB 5/11/26, 12:19:51 AM"},"e78":{"role":"cell","name":"package.json"},"e79":{"role":"link","name":"package.json"},"e80":{"role":"cell","name":"1.6 kB"},"e81":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e82":{"role":"row","name":"README.md 6.5 kB 5/11/26, 12:19:51 AM"},"e83":{"role":"cell","name":"README.md"},"e84":{"role":"link","name":"README.md"},"e85":{"role":"cell","name":"6.5 kB"},"e86":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e87":{"role":"row","name":"SOUL.md 6.9 kB 5/11/26, 12:19:51 AM"},"e88":{"role":"cell","name":"SOUL.md"},"e89":{"role":"link","name":"SOUL.md"},"e90":{"role":"cell","name":"6.9 kB"},"e91":{"role":"cell","name":"5/11/26, 12:19:51 AM"},"e92":{"role":"row","name":"tsconfig.json 524 B 5/11/26, 12:19:51 AM"},"e93":{"role":"cell","name":"tsconfig.json"},"e94":{"role":"link","name":"tsconfig.json"},"e95":{"role":"cell","name":"524 B"},"e96":{"role":"cell","name":"5/11/26, 12:19:51 AM"}},"hint":"Use act with kind=\"click\" and ref=\"eN\" to click elements. Or navigate directly to a /url visible in the snapshot."}}}
{"type":"tool_result","timestamp":"2026-05-11T11:27:37.904Z","toolName":"memory_search","args":{"query":"research rules RULES.md"},"result":"Error: 401 Incorrect API key provided: your-ope*******-key. You can find your API key at https://platform.openai.com/account/api-keys.\n\nTroubleshooting URL: https://docs.langchain.com/oss/javascript/langchain/errors/MODEL_AUTHENTICATION/\n"}
{"type":"tool_result","timestamp":"2026-05-11T11:27:42.434Z","toolName":"browser","args":{"url":"file:///Users/user/Projects/dexter/.dexter/memory/","action":"navigate"},"result":{"data":{"ok":true,"url":"file:///Users/user/Projects/dexter/.dexter/memory/","title":"Index of /Users/user/Projects/dexter/.dexter/memory/","hint":"Page loaded. Call snapshot to see page structure and find elements to interact with."}}}
{"type":"tool_result","timestamp":"2026-05-11T11:27:44.508Z","toolName":"browser","args":{"action":"snapshot"},"result":{"data":{"url":"file:///Users/user/Projects/dexter/.dexter/memory/","title":"Index of /Users/user/Projects/dexter/.dexter/memory/","snapshot":"- generic [active] [ref=e1]:\n  - heading \"Index of /Users/user/Projects/dexter/.dexter/memory/\" [level=1] [ref=e2]\n  - link \"[parent directory]\" [ref=e4] [cursor=pointer]:\n    - /url: /Users/user/Projects/dexter/.dexter/memory/..\n  - table [ref=e5]:\n    - rowgroup [ref=e6]:\n      - row \"Name Size Date Modified\" [ref=e7]:\n        - button \"Name\" [ref=e8] [cursor=pointer]\n        - button \"Size\" [ref=e9] [cursor=pointer]\n        - button \"Date Modified\" [ref=e10] [cursor=pointer]\n    - rowgroup [ref=e11]:\n      - row \"index.sqlite 52.0 kB 5/11/26, 12:23:52 AM\" [ref=e12]:\n        - cell \"index.sqlite\" [ref=e13]:\n          - link \"index.sqlite\" [ref=e14] [cursor=pointer]:\n            - /url: /Users/user/Projects/dexter/.dexter/memory/index.sqlite\n        - cell \"52.0 kB\" [ref=e15]\n        - cell \"5/11/26, 12:23:52 AM\" [ref=e16]","truncated":false,"refCount":15,"refs":{"e1":{"role":"generic"},"e2":{"role":"heading","name":"Index of /Users/user/Projects/dexter/.dexter/memory/"},"e4":{"role":"link","name":"[parent directory]"},"e5":{"role":"table"},"e6":{"role":"rowgroup"},"e7":{"role":"row","name":"Name Size Date Modified"},"e8":{"role":"button","name":"Name"},"e9":{"role":"button","name":"Size"},"e10":{"role":"button","name":"Date Modified"},"e11":{"role":"rowgroup"},"e12":{"role":"row","name":"index.sqlite 52.0 kB 5/11/26, 12:23:52 AM"},"e13":{"role":"cell","name":"index.sqlite"},"e14":{"role":"link","name":"index.sqlite"},"e15":{"role":"cell","name":"52.0 kB"},"e16":{"role":"cell","name":"5/11/26, 12:23:52 AM"}},"hint":"Use act with kind=\"click\" and ref=\"eN\" to click elements. Or navigate directly to a /url visible in the snapshot."}}}
{"type":"tool_result","timestamp":"2026-05-11T11:27:45.918Z","toolName":"read_file","args":{"path":"README.md"},"result":{"data":{"path":"README.md","content":"# Dexter 🤖\n\nDexter is an autonomous financial research agent that thinks, plans, and learns as it works. It performs analysis using task planning, self-reflection, and real-time market data. Think Claude Code, but built specifically for financial research.\n\n<img width=\"665\" height=\"452\" alt=\"Screenshot 2026-04-02 at 4 16 57 PM\" src=\"https://github.com/user-attachments/assets/02418111-5f48-4a66-be5d-dc9bf9806284\" />\n\n## Table of Contents\n\n- [👋 Overview](#-overview)\n- [✅ Prerequisites](#-prerequisites)\n- [💻 How to Install](#-how-to-install)\n- [🚀 How to Run](#-how-to-run)\n- [📊 How to Evaluate](#-how-to-evaluate)\n- [🐛 How to Debug](#-how-to-debug)\n- [📱 How to Use with WhatsApp](#-how-to-use-with-whatsapp)\n- [🤝 How to Contribute](#-how-to-contribute)\n- [📄 License](#-license)\n\n## ⚠️ Disclaimer\n\nThis project is for **educational, entertainment, and informational purposes only**. It is not intended for real trading or investment.\n\n- Not financial, investment, tax, or legal advice\n- No guarantees of accuracy, completeness, or fitness for any purpose\n- Outputs may be incorrect, incomplete, or out of date\n- Creator and contributors assume no liability for any financial losses or damages\n- Consult a licensed financial advisor before making investment decisions\n- Past performance does not indicate future results\n\nBy using this software, you agree to use it solely for learning and informational purposes and accept all risks associated with its use.\n\n## 👋 Overview\n\nDexter takes complex financial questions and turns them into clear, step-by-step research plans. It runs those tasks using live market data, checks its own work, and refines the results until it has a confident, data-backed answer.  \n\n**Key Capabilities:**\n- **Intelligent Task Planning**: Automatically decomposes complex queries into structured research steps\n- **Autonomous Execution**: Selects and executes the right tools to gather financial data\n- **Self-Validation**: Checks its own work and iterates until tasks are complete\n- **Real-Time Financial Data**: Access to income statements, balance sheets, and cash flow statements\n- **Safety Features**: Built-in loop detection and step limits to prevent runaway execution\n\n[![Twitter Follow](https://img.shields.io/twitter/follow/virattt?style=social)](https://twitter.com/virattt) [![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?style=social&logo=discord)](https://discord.gg/jpGHv2XB6T)\n\n<img width=\"1042\" height=\"638\" alt=\"Screenshot 2026-02-18 at 12 21 25 PM\" src=\"https://github.com/user-attachments/assets/2a6334f9-863f-4bd2-a56f-923e42f4711e\" />\n\n\n## ✅ Prerequisites\n\n- [Bun](https://bun.com) runtime (v1.0 or higher)\n- OpenAI API key (get [here](https://platform.openai.com/api-keys))\n- Financial Datasets API key (get [here](https://financialdatasets.ai))\n- Exa API key (get [here](https://exa.ai)) - optional, for web search\n\n#### Installing Bun\n\nIf you don't have Bun installed, you can install it using curl:\n\n**macOS/Linux:**\n```bash\ncurl -fsSL https://bun.com/install | bash\n```\n\n**Windows:**\n```bash\npowershell -c \"irm bun.sh/install.ps1|iex\"\n```\n\nAfter installation, restart your terminal and verify Bun is installed:\n```bash\nbun --version\n```\n\n## 💻 How to Install\n\n1. Clone the repository:\n```bash\ngit clone https://github.com/virattt/dexter.git\ncd dexter\n```\n\n2. Install dependencies with Bun:\n```bash\nbun install\n```\n\n3. Set up your environment variables:\n```bash\n# Copy the example environment file\ncp env.example .env\n\n# Edit .env and add your API keys (if using cloud providers)\n# OPENAI_API_KEY=your-openai-api-key\n# ANTHROPIC_API_KEY=your-anthropic-api-key (optional)\n# GOOGLE_API_KEY=your-google-api-key (optional)\n# XAI_API_KEY=your-xai-api-key (optional)\n# OPENROUTER_API_KEY=your-openrouter-api-key (optional)\n\n# Institutional-grade market data for agents\n# FINANCIAL_DATASETS_API_KEY=your-financial-datasets-api-key\n\n# (Optional) If using Ollama locally\n# OLLAMA_BASE_URL=http://127.0.0.1:11434\n\n# Web Search (Exa preferred, Tavily fallback)\n# EXASEARCH_API_KEY=your-exa-api-key\n# TAVILY_API_KEY=your-tavily-api-key\n```\n\n## 🚀 How to Run\n\nRun Dexter in interactive mode:\n```bash\nbun start\n```\n\nOr with watch mode for development:\n```bash\nbun dev\n```\n\n## 📊 How to Evaluate\n\nDexter includes an evaluation suite that tests the agent against a dataset of financial questions. Evals use LangSmith for tracking and an LLM-as-judge approach for scoring correctness.\n\n**Run on all questions:**\n```bash\nbun run src/evals/run.ts\n```\n\n**Run on a random sample of data:**\n```bash\nbun run src/evals/run.ts --sample 10\n```\n\nThe eval runner displays a real-time UI showing progress, current question, and running accuracy statistics. Results are logged to LangSmith for analysis.\n\n## 🐛 How to Debug\n\nDexter logs all tool calls to a scratchpad file for debugging and history tracking. Each query creates a new JSONL file in `.dexter/scratchpad/`.\n\n**Scratchpad location:**\n```\n.dexter/scratchpad/\n├── 2026-01-30-111400_9a8f10723f79.jsonl\n├── 2026-01-30-143022_a1b2c3d4e5f6.jsonl\n└── ...\n```\n\nEach file contains newline-delimited JSON entries tracking:\n- **init**: The original query\n- **tool_result**: Each tool call with arguments, raw result, and LLM summary\n- **thinking**: Agent reasoning steps\n\n**Example scratchpad entry:**\n```json\n{\"type\":\"tool_result\",\"timestamp\":\"2026-01-30T11:14:05.123Z\",\"toolName\":\"get_income_statements\",\"args\":{\"ticker\":\"AAPL\",\"period\":\"annual\",\"limit\":5},\"result\":{...},\"llmSummary\":\"Retrieved 5 years of Apple annual income statements showing revenue growth from $274B to $394B\"}\n```\n\nThis makes it easy to inspect exactly what data the agent gathered and how it interpreted results.\n\n## 📱 How to Use with WhatsApp\n\nChat with Dexter through WhatsApp by linking your phone to the gateway. Messages you send to yourself are processed by Dexter and responses are sent back to the same chat.\n\n**Quick start:**\n```bash\n# Link your WhatsApp account (scan QR code)\nbun run gateway:login\n\n# Start the gateway\nbun run gateway\n```\n\nThen open WhatsApp, go to your own chat (message yourself), and ask Dexter a question.\n\nFor detailed setup instructions, configuration options, and troubleshooting, see the [WhatsApp Gateway README](src/gateway/channels/whatsapp/README.md).\n\n## 🤝 How to Contribute\n\n1. Fork the repository\n2. Create a feature branch\n3. Commit your changes\n4. Push to the branch\n5. Create a Pull Request\n\n**Important**: Please keep your pull requests small and focused.  This will make it easier to review and merge.\n\n\n## 📄 License\n\nThis project is licensed under the MIT License.\n","truncated":false,"totalLines":193}}}

After:

{"type":"init","content":"Show me my current research rules from .dexter/RULES.md","timestamp":"2026-05-11T11:22:12.873Z"}
{"type":"tool_result","timestamp":"2026-05-11T11:22:14.176Z","toolName":"read_file","args":{"path":".dexter/RULES.md"},"result":"Error: ENOENT: no such file or directory, access '/Users/user/Projects/dexter/.dexter/RULES.md'"}

Image

@swrzalek
Copy link
Copy Markdown
Contributor Author

This fixes #261. There is still an issue with tool hanging #245 that will be fixed in separate PR.

@virattt virattt force-pushed the fix-rules-command branch 2 times, most recently from 377d05f to 8862fd2 Compare May 11, 2026 19:41
@virattt
Copy link
Copy Markdown
Owner

virattt commented May 11, 2026

Thanks!

@virattt virattt merged commit aadaef1 into virattt:main May 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants