跪拜 Guibai
← All articles
Artificial Intelligence

Cursor's Agent Loop Is Just 30 Lines of Code

By 橘子星 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Cursor, Copilot, and Claude Code all run the same pattern: a model in a loop calling tools. Understanding that loop — and how to isolate shell execution in a child process — is the difference between treating these tools as magic and building your own custom agent that actually ships code.

Summary

A mini-cursor built in under 300 lines of JavaScript strips AI coding assistants down to their core: a large language model bound to four tools — read file, write file, list directory, and execute command. The model decides which tool to invoke, and a Node.js child process runs long shell commands like `pnpm install` without blocking the agent.

The agent runs a ReAct loop that feeds tool results back into the conversation context, letting the model adjust its next move. A single prompt to create a React TodoList app triggers a sequence of Vite scaffolding, file writes, dependency installation, and dev-server startup — all driven by tool calls, not magic.

LangChain's `bindTools()` converts tool signatures into OpenAI function-calling format, while Zod schemas enforce parameter shapes. The system prompt includes explicit correct and incorrect usage examples to prevent the model from doubling up `cd` commands inside shell invocations.

Takeaways
An AI coding agent is a ReAct loop that alternates between model reasoning and tool execution, capped at a max iteration count to prevent infinite loops.
LangChain's `tool()` wrapper pairs an async function with a Zod schema so the model knows exactly what parameters to supply.
`bindTools()` converts tool definitions into OpenAI function-calling format, making the model aware of available capabilities.
Shell commands run in a separate child process via `spawn` with `stdio: 'inherit'` to avoid blocking the single-threaded Node.js main process and to show real-time output.
Tool results are fed back as `ToolMessage` objects into the message history, giving the model the context it needs to decide the next step.
Explicit correct/incorrect examples in the system prompt prevent the model from nesting `cd` inside commands when a `workingDirectory` parameter already exists.
Conclusions

The entire agent is a state machine where the only state is the message array; there is no planner, no tree search, and no separate memory module.

Error handling inside tools returns friendly strings rather than throwing exceptions, which lets the model read the failure and self-correct on the next loop iteration.

Using `spawn` instead of `exec` matters because `spawn` streams output — essential for long-running commands like `pnpm install` where the user needs to see progress.

The system prompt is doing heavy lifting: without the explicit rule against `cd` inside commands, the model reliably produces broken shell invocations.

Concepts & terms
ReAct Loop
A reasoning-and-acting pattern where a language model alternates between deciding which tool to call (Think), executing that tool (Act), and feeding the result back into context (Observe) until a goal is reached.
Tool Binding (bindTools)
A LangChain method that converts tool definitions — name, description, and Zod parameter schema — into the function-calling format that OpenAI-compatible models expect, so the model can request tool invocations in its responses.
ToolMessage
A LangChain message type that carries the result of a tool execution back into the conversation history, paired with a `tool_call_id` so the model can associate the result with the request that produced it.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗