跪拜 Guibai
← All articles
Artificial Intelligence

Give Your AI Agent Hands: Implementing read_file Tool Calls in Python

By 师夷长技以自愈 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

A model that can request files stops guessing from training-data templates and answers from the actual project. The path-traversal guard and the two-call message flow are the minimum scaffolding for any filesystem-touching agent, and the DeepSeek reasoning_content fix is the kind of integration detail that turns a demo into something that survives a move across providers.

Summary

This step in a Python agent-building series takes a plain chat bot and gives it a real tool: read_file. The model no longer answers from memory; it issues a structured order for a file path, the Python program reads the file, and the model receives the content before replying. The restaurant metaphor frames it clearly: AI is the guest, Python is the kitchen, and the JSON Schema is the menu the guest orders from.

Three pieces make the flow work. A tool definition declares read_file with one required path parameter. A Python function validates that the resolved path stays inside the project root (blocking ../ and absolute paths), reads the file, and caps the read at 8,000 bytes. The chat layer calls the model once to get a tool call, then sends the file content back as a tool message to get the final answer. The post also flags a DeepSeek-specific bug: thinking models require reasoning_content to be passed back exactly, or the second call returns a 400.

Takeaways
— The series is a Python port of Teernage's 'Hand-rolled AI Agent' Node/TS column, with code at wanghesong2019/powercode-py.
— The read_file tool is defined as a JSON Schema object specifying a required string parameter named path.
— read_file_tool resolves the requested path to an absolute path and allows reads only when the project root is one of its parent directories, blocking traversal like ../secret.txt.
— Files are truncated to 8,000 bytes, then the remainder is replaced with a note, to keep token use and latency down.
— The chat flow needs two model calls: ask_with_tools returns the tool call, then answer_after_read_file sends the file content back as a tool message to get the final answer.
— DeepSeek thinking models (like deepseek-v4-flash) return a reasoning_content field that must be carried over when reconstructing assistant messages, or the second call fails with a 400.
Conclusions

The restaurant metaphor captures a fundamental division of labor: a language model never executes anything, it only emits structured requests; the application decides what to run. That separation is what makes tool calling a safe extension of model capabilities.

The path validation code isn't over-engineering. A model can emit a path like ../../../etc/passwd; without a guard against the project root, the agent would hand sensitive files to the model. Treating this as a lifeline is the right default for any agent that touches the filesystem.

The two-call pattern is the recurring skeleton of agent design: ask for intent, act, then feed the result back. The DeepSeek reasoning_content quirk shows that provider-specific message history rules can break this flow, so porting agents between APIs demands careful attention to what gets returned.

Concepts & terms
Tool calling (function calling)
A protocol where a language model outputs a structured request naming a function and its arguments instead of a final answer; the application executes that function and returns the result as a tool message.
JSON Schema
A machine-readable format for describing the parameters a tool accepts, telling the model what fields and types to provide when it requests a tool call.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗