Skip to main content

Overview

Polaris IDE’s AI agent is equipped with a comprehensive set of tools that enable it to interact with your codebase autonomously. These tools allow the agent to read and modify files, analyze code structure, search for patterns, execute commands, and understand project context.

Tool calling system

The agent uses the AI SDK’s tool calling system to execute structured actions:
import { tool, zodSchema } from "ai"
import { z } from "zod"

// Each tool is defined with:
// 1. Description (tells AI when to use it)
// 2. Input schema (validates parameters)
// 3. Execute function (performs the action)

const exampleTool = tool({
  description: "What this tool does and when to use it",
  inputSchema: zodSchema(
    z.object({
      param: z.string().describe("Parameter description")
    })
  ),
  execute: async ({ param }) => {
    // Tool implementation
    return "Result"
  }
})
All tools use Zod schemas for type-safe parameter validation, ensuring the AI provides correctly formatted inputs.

Available tools

File operations

Tools for reading, writing, and managing project files.

readFile

Read the contents of a file by path.

writeFile

Create or update a file (parent folders created automatically).

deleteFile

Delete a file or folder (recursive deletion for folders).

listFiles

List all files and folders in a directory.

getProjectStructure

Get complete file tree of the project.
readFile: tool({
  description: "Read the contents of a file in the project",
  inputSchema: zodSchema(
    z.object({
      path: z.string().describe("File path relative to project root (e.g., 'src/index.ts')")
    })
  ),
  execute: async ({ path }) => {
    const file = await convex.query(api.system.readFileByPath, {
      internalKey,
      projectId,
      path
    })
    return file?.content ?? "File not found"
  }
})

LSP (Language Server Protocol) tools

Advanced code analysis using TypeScript’s Language Service.

findSymbol

Search for functions, classes, variables, interfaces, types by name.

getReferences

Find all references to a symbol at a specific location.

getDiagnostics

Get TypeScript errors, warnings, and suggestions for a file.

goToDefinition

Find where a symbol is defined.
findSymbol: tool({
  description: "Search for symbols (functions, classes, variables, interfaces, types) in the codebase by name.",
  inputSchema: zodSchema(
    z.object({
      query: z.string().describe("Symbol name or partial name to search for"),
      kind: z.enum(["function", "class", "variable", "interface", "type", "all"]).optional()
    })
  ),
  execute: async ({ query, kind = "all" }) => {
    // Creates TypeScript language service
    // Searches navigation items across all files
    // Returns matches with file path and location
    return `Found 5 symbol(s):\n[function] handleClick - src/utils.ts:42:1`
  }
})
LSP tools create a full TypeScript language service in-memory, providing the same code intelligence as your IDE.

Search tools

Powerful search capabilities for finding code patterns and files.

searchFiles

Search file contents using regex patterns.

searchCodebase

AST-aware search for imports, functions, classes, variables, exports, calls.

findFilesByPattern

Find files by name using glob patterns.
searchFiles: tool({
  description: "Search file contents using regex patterns. Returns matching lines with file path, line number, and context.",
  inputSchema: zodSchema(
    z.object({
      pattern: z.string().describe("Regex pattern to search for (e.g., 'TODO', 'function\\s+\\w+', 'import.*react')"),
      filePattern: z.string().optional().describe("Optional glob pattern to filter files (e.g., '*.ts', 'src/**/*.tsx')"),
      caseSensitive: z.boolean().optional().describe("Whether the search is case-sensitive (default: false)")
    })
  ),
  execute: async ({ pattern, filePattern, caseSensitive = false }) => {
    // Compiles regex pattern
    // Filters files by glob pattern if provided
    // Returns matches with context (max 50 results)
    return `Found 3 match(es):\nsrc/app.ts:15:3 - // TODO: Implement this feature`
  }
})

Context tools

Intelligent file relevance scoring for understanding project context.

getRelevantFiles

Find files most relevant to a query using import analysis, symbol matching, edit history, and file proximity.
getRelevantFiles: tool({
  description: "Find files most relevant to a query or current context. Returns top N most relevant files with scores and reasons.",
  inputSchema: zodSchema(
    z.object({
      query: z.string().describe("Search query or context description"),
      currentFile: z.string().optional().describe("Current file path for context"),
      maxFiles: z.number().optional().describe("Maximum files to return (default: 5)")
    })
  ),
  execute: async ({ query, currentFile, maxFiles = 5 }) => {
    // Scores files based on:
    // - Direct imports (weight: 10)
    // - Shared symbols (weight: 7)
    // - Recent edits (weight: 5)
    // - File proximity (weight: 3)
    // - Similar file type (weight: 2)
    return `Found 3 relevant file(s):\n1. src/auth.ts [score: 15.0] (Imported by current file, Contains query terms: auth, login)`
  }
})

Terminal tools

Safe command execution with whitelist-based security.

executeCommand

Execute safe terminal commands with 30-second timeout and 1MB output limit.
Security: Only whitelisted commands are allowed: npm, bun, pnpm, yarn, git, node, tsc, eslint, prettier, test, npx. Dangerous operations like rm -rf, sudo, curl, wget, ssh, chmod are blocked.
executeCommand: tool({
  description: "Execute safe terminal commands. Commands have a 30-second timeout and 1MB output limit.",
  inputSchema: zodSchema(
    z.object({
      command: z.string().describe("The command to execute (e.g., 'npm install', 'git status')"),
      cwd: z.string().optional().describe("Working directory relative to project root")
    })
  ),
  execute: async ({ command, cwd }) => {
    // Validates command against whitelist
    // Checks for blocked patterns (rm -rf, sudo, etc.)
    // Executes with timeout and output limits
    // Returns stdout/stderr or error message
    return "Command completed successfully (no output)"
  }
})

Agent integration with Trigger.dev

The agent runs as a Trigger.dev background task for reliable, long-running execution:
1

Task initialization

process-message task is triggered with message ID.
2

Context loading

Task loads conversation history and project context from Convex.
3

Tool creation

All tool categories are instantiated with project scope and internal key.
4

AI generation with tools

Streaming text generation with tool calling (max 10 steps).
5

Real-time updates

Tool calls and results streamed back to database as they execute.
export const processMessage = task({
  id: "process-message",
  run: async (payload: ProcessMessagePayload, { ctx }) => {
    const { messageId } = payload
    
    // Load context
    const context = await convex.query(api.system.getMessageContext, {
      internalKey,
      messageId
    })
    
    // Create tools
    const fileTools = createFileTools(context.projectId, internalKey)
    const lspTools = createLSPTools(context.projectId, internalKey)
    const searchTools = createSearchTools(context.projectId, internalKey)
    const terminalTools = createTerminalTools(context.projectId, internalKey)
    const contextTools = createContextTools(context.projectId, internalKey)
    
    const tools = {
      ...fileTools,
      ...lspTools,
      ...searchTools,
      ...terminalTools,
      ...contextTools
    }
    
    // Generate response with tools
    const response = await streamTextWithToolsPreferCerebras({
      system: SYSTEM_PROMPT,
      messages: context.messages,
      tools,
      maxSteps: 10,
      maxTokens: 2000
    })
  }
})

Tool execution flow

When the AI decides to use a tool:
1

AI selects tool

Based on user request and system prompt, AI chooses appropriate tool with parameters.
2

Schema validation

Zod schema validates tool parameters before execution.
3

Tool execution

Tool’s execute function runs with validated parameters.
4

Result streaming

Tool call and result are streamed to database for real-time UI updates.
5

AI continues

AI receives tool result and continues generation (up to maxSteps).
// Example tool execution sequence:

User: "Find all TODO comments in TypeScript files"

// Step 1: AI calls searchFiles tool
{
  name: "searchFiles",
  args: {
    pattern: "TODO",
    filePattern: "**/*.ts",
    caseSensitive: false
  }
}

// Step 2: Tool executes and returns results
"Found 5 match(es):\nsrc/utils.ts:42:5 - // TODO: Optimize this loop"

// Step 3: AI uses results to generate response
"I found 5 TODO comments in your TypeScript files. Here's a summary..."

Error handling

Tools handle errors gracefully and return user-friendly messages:
try {
  const file = await convex.query(api.system.readFileByPath, {
    internalKey,
    projectId,
    path
  })
  
  if (!file) {
    return `File not found: ${path}`
  }
  
  return file.content ?? ""
} catch (error) {
  return `Error reading file: ${error instanceof Error ? error.message : "Unknown error"}`
}
Tools never throw exceptions - they always return a string result (success or error message) so the AI can handle failures gracefully.

Performance considerations

  • Tool result limits: Search tools limit results to 50 items to prevent overwhelming the AI context
  • Output truncation: Terminal tool truncates output to 1MB to prevent excessive data transfer
  • Timeout protection: Terminal commands have 30-second timeout to prevent hanging
  • Concurrent execution: Multiple tools can be called in a single step when AI needs parallel operations

Source code reference

Implementation details:
  • File tools: src/lib/ai-tools.ts:25
  • LSP tools: src/lib/lsp-tools.ts:169
  • Search tools: src/lib/search-tools.ts:169
  • Context tools: src/lib/context-tools.ts:307
  • Terminal tools: src/lib/terminal-tools.ts:172
  • Task integration: trigger/tasks/process-message.ts:70

Build docs developers (and LLMs) love