Skip to main content
Build your own Warp Grep harness in any language. This page documents the raw API protocol—message structure, tool formats, and result formatting.
For a complete implementation, see the Python Guide. For TypeScript SDK wrappers, see Tool.

Message Flow

The agent runs a multi-turn conversation with max 4 turns:
system → user → assistant → user → assistant → ... → finish
TurnRoleContent
0systemSystem prompt with tool definitions
1userRepo structure + search query
2assistantAgent’s tool calls
3userTool execution results
4+Repeat until finish is called

Initial User Message

The first user message contains two parts:
  1. Repository structure — pre-run list_directory at root with depth 2
  2. Search query — what the agent needs to find
<repo_structure>
myproject/
  src/
    auth/
    db/
    utils/
  tests/
  config.py
  main.py
  README.md
</repo_structure>

<search_string>
Find where user authentication is implemented
</search_string>

API Call

curl -X POST https://api.morphllm.com/v1/chat/completions \
  -H "Authorization: Bearer $MORPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "morph-warp-grep-v1",
    "messages": [
      {"role": "system", "content": "<system prompt>"},
      {"role": "user", "content": "<repo_structure>...</repo_structure>\n<search_string>Find auth middleware</search_string>"}
    ],
    "temperature": 0.0,
    "max_tokens": 2048
  }'

Agent Response Format

The agent first thinks, then outputs tool calls using nested XML:
<think>
Looking for authentication. I'll grep for auth-related patterns
and explore the auth directory structure.
</think>

<grep>
  <pattern>authenticate</pattern>
  <sub_dir>src/</sub_dir>
</grep>

<grep>
  <pattern>login</pattern>
  <sub_dir>src/</sub_dir>
</grep>

<list_directory>
  <path>src/auth</path>
</list_directory>

Tools

Search for regex pattern matches using ripgrep.Agent calls:
<grep>
  <pattern>(authenticate|authorize)</pattern>
  <sub_dir>src/auth/</sub_dir>
  <glob>*.py</glob>
</grep>
ElementRequiredDescription
<pattern>YesRegex pattern to search
<sub_dir>NoDirectory to search (default .)
<glob>NoFile filter like *.py or *.{ts,tsx}
You execute:
rg --line-number --no-heading --color never -C 1 "(authenticate|authorize)" src/auth/ --glob "*.py"
You return:
<grep pattern="(authenticate|authorize)" sub_dir="src/auth/">
src/auth/login.py-44-
src/auth/login.py:45:def authenticate(username, password):
src/auth/login.py-46-    """Validate user credentials."""
--
src/auth/login.py-77-
src/auth/login.py:78:def authorize(user, resource):
src/auth/login.py-79-    """Check if user can access resource."""
</grep>
Output format: Match lines use : separator (filepath:linenum:content), context lines use - separator (filepath-linenum-content), groups separated by --.

Result Format

After executing tools, wrap each result in XML tags that echo the query:
<grep pattern="authenticate" sub_dir="src/">
src/auth/login.py:45:def authenticate(username, password):
src/middleware/session.py:12:from auth import authenticate
</grep>

<list_directory path="src/auth/">
src/auth/
  login.py
  session.py
  middleware/
</list_directory>

<read path="src/auth/login.py" lines="1-20">
1|import hashlib
2|import secrets
...
20|    return hashed
</read>

Turn Counter

After tool results, append a turn counter and context budget:
You have used 1 turn and have 3 remaining.
<context_budget>92% (147K/160K chars)</context_budget>
Turn messages by turn number:
TurnMessage
1You have used 0 turns and have 4 remaining
2You have used 1 turn and have 3 remaining
3You have used 2 turns and have 2 remaining
4You have used 3 turns, you only have 1 turn remaining. You have run out of turns to explore the code base and MUST call the finish tool now

Output Limits

Tools enforce output limits to prevent context explosion:
ToolMax LinesOn Exceed
grep200Replace with “query not specific enough, tool called tried to return too much context and failed”
list_directory200Same
read800Truncate with warning

Complete Example

Here’s the full message flow for a 2-turn search:
User message:
<repo_structure>
myapp/
  src/
    auth/
    api/
    models/
  tests/
  package.json
</repo_structure>

<search_string>
Find where JWT tokens are validated
</search_string>
Assistant response:
<think>
Looking for JWT validation. I'll grep for jwt-related patterns
and check the auth directory.
</think>

<grep>
  <pattern>jwt|JWT</pattern>
  <sub_dir>src/</sub_dir>
</grep>

<grep>
  <pattern>verify.*token</pattern>
  <sub_dir>src/</sub_dir>
</grep>

<list_directory>
  <path>src/auth</path>
</list_directory>
User message (tool results):
<grep pattern="jwt|JWT" sub_dir="src/">
src/auth/jwt.ts-14-
src/auth/jwt.ts:15:import jwt from 'jsonwebtoken';
src/auth/jwt.ts-16-
--
src/auth/jwt.ts-44-
src/auth/jwt.ts:45:export function verifyJWT(token: string) {
src/auth/jwt.ts-46-  return jwt.verify(token, SECRET);
</grep>

<grep pattern="verify.*token" sub_dir="src/">
src/auth/jwt.ts-44-
src/auth/jwt.ts:45:export function verifyJWT(token: string) {
src/auth/jwt.ts-46-  return jwt.verify(token, SECRET);
--
src/middleware/auth.ts-22-
src/middleware/auth.ts:23:  const valid = verifyToken(req.headers.authorization);
src/middleware/auth.ts-24-  if (!valid) return res.status(401).send();
</grep>

<list_directory path="src/auth">
src/auth/
  index.ts
  jwt.ts
  session.ts
</list_directory>

You have used 1 turn and have 3 remaining.
<context_budget>94% (150K/160K chars)</context_budget>
Assistant response:
<think>
Found the JWT validation in src/auth/jwt.ts and it's used in middleware.
I have enough context to finish.
</think>

<finish>
  <file>
    <path>src/auth/jwt.ts</path>
    <lines>1-60</lines>
  </file>
  <file>
    <path>src/middleware/auth.ts</path>
    <lines>1-40</lines>
  </file>
</finish>

System Prompt

You are a code search agent. Your task is to find all relevant code for a given query.

<workflow>
You have exactly 4 turns. The 4th turn MUST be a `finish` call. Each turn allows up to 8 parallel tool calls.

- Turn 1: Map the territory OR dive deep (based on query specificity)
- Turn 2-3: Refine based on findings
- Turn 4: MUST call `finish` with all relevant code locations
- You MAY call `finish` early if confident—but never before at least 1 search turn.
</workflow>

<tools>
### list_directory
Directory tree view. Shows structure of a path, optionally filtered by regex pattern.

Elements:
- <path> (required): Directory path to list
- <pattern> (optional): Regex pattern to filter results

### grep
Search for pattern matches across files using ripgrep.

Elements:
- <pattern> (required): Search pattern (regex)
- <sub_dir> (optional): Subdirectory to search in
- <glob> (optional): File pattern filter like *.py

### read
Read file contents with optional line ranges.

Elements:
- <path> (required): File path to read
- <lines> (optional): Line ranges like 1-50,75-80

### finish
Submit final answer with all relevant code locations.

Contains one or more <file> elements, each with:
- <path> (required): File path
- <lines> (optional): Line ranges (* for entire file)
</tools>

<output_format>
EVERY response MUST:
1. First, wrap reasoning in <think>...</think> tags
2. Then, output tool calls as XML elements

Example:
<think>
This is a specific query about authentication.
</think>

<grep>
  <pattern>authenticate</pattern>
  <sub_dir>src/</sub_dir>
</grep>

<list_directory>
  <path>src/auth</path>
</list_directory>

No commentary outside <think>. No explanations after tool calls.
</output_format>

Begin your exploration now to find code relevant to the query.

Implementation Guide

For a complete working implementation, see the Python Guide which covers:
  • API call function
  • XML parsing for tool calls
  • Tool executors (ripgrep, file reads, tree)
  • Result formatters
  • Complete agent loop