












지능 에이전트(AI Agent)를 구축할 때, 우리는 종종 에이전트가 파일을 읽고, 쓰고, 검색하고, 편집할 수 있도록 해야 합니다. DeepAgents 프레임워크는 Backend(백엔드) 메커니즘을 통해 이 기능을 구현하여 에이전트에게 안전하고 제어 가능한 파일 작업 환경을 제공합니다. 본 글에서는 Backend의 개념과 사용 방법을 심층적으로 탐구하고, 네 가지 점진적인 예제를 통해 그 강력한 기능을 보여줍니다.
Backend는 DeepAgents 프레임워크의 핵심 추상 개념으로, 에이전트가 파일 시스템과 어떻게 상호작용할지 정의합니다. Backend를 통해 에이전트는 다음과 같은 작업을 수행할 수 있습니다:
ls_info)read) write) grep_raw) glob_info) edit) Backend의 핵심 가치는 보안 과 유연성에 있습니다:Agent의 파일 작업을 특정 디렉토리 내에서 제한하여 권한 상승 접근을 방지하고, 다양한 저장 매체(로컬 파일 시스템, 메모리, 클라우드 저장소 등)를 지원합니다.
DeepAgents 프레임워크는 다양한 Backend 구현을 제공하여 다양한 시나리오의 요구사항을 충족합니다:
OpenSandboxBackend:OpenSandbox를 기반으로 한 오픈 소스 사상 솔루션DaytonaBackend:Daytona를 기반으로 한 클라우드 사상 솔루션BackendProtocol 인터페이스를 구현하여 커스텀 저장 로직을 정의DictBackend(메모리 저장)、RedisBackend(Redis 저장) 등| 백엔드 유형 | 파일 작업 | 명령 실행 | 영구 저장 | 보안 격리 | 표준 시나리오 |
|---|---|---|---|---|---|
| FilesystemBackend | ✅ | ❌ | ✅ | 중간(가상 모드) | 로컬 파일 처리 |
| LocalShellBackend | ✅ | ✅(지역) | ✅ | 중간(가상 모드) | 지역 스크립트 실행 |
| SandboxBackend | ✅ | ✅(사상장) | 선택 | 높음(완전 분리) | 클라우드 보안 실행 |
| 사용자 정의 Backend | 사용자 정의 | 사용자 정의 | 사용자 정의 | 사용자 정의 | 특별 요구사항 |
가장 간단한 Agent 구성은 Backend를 사용하지 않고, 오직 도구 호출에만 의존하여 작업을 수행합니다:
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
# 创建内存检查点保存器
checkpointer = InMemorySaver()
# 创建基础Agent
agent = create_deep_agent(
model=llm,
tools=[web_search],
#checkpointer=checkpointer,
system_prompt='你是一个助手,请根据用户输入的指令,进行相应的操作。'
)
특징:
Agent이 파일을 작동해야 할 때,FilesystemBackend가장 흔하게 선택되는 것입니다:
import os
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
from langgraph.checkpoint.memory import InMemorySaver
checkpointer = InMemorySaver()
# 创建Agent工作目录
temp_workspace = "./agent_workspace"
os.makedirs(temp_workspace, exist_ok=True)
agent = create_deep_agent(
model=llm,
tools=[web_search],
checkpointer=checkpointer,
backend=FilesystemBackend(
root_dir=temp_workspace,
virtual_mode=True, # 防止Agent通过`../../`跳出根目录
),
system_prompt='你是一个助手,请根据用户输入的指令,进行相应的操作。'
)
핵심 파라미터:
root_dir:지정된 Agent의 작업 루트 디렉토리virtual_mode=True:가상 모드를 활성화하여 경로 통과 공격(예: ../../etc/passwd)을 방지합니다.적용 시나리오:
Agent이 파일 작업뿐만 아니라 shell 명령을 실행해야 하는 경우, LocalShellBackend는 더 나은 선택입니다:
import os
import sys
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend, LocalShellBackend
from langgraph.checkpoint.memory import InMemorySaver
checkpointer = InMemorySaver()
temp_workspace = "./agent_workspace"
os.makedirs(temp_workspace, exist_ok=True)
agent = create_deep_agent(
model=llm,
tools=[web_search],
checkpointer=checkpointer,
backend=LocalShellBackend(
root_dir=temp_workspace,
virtual_mode=True,
timeout=30, # 命令执行超时时间(秒)
max_output_bytes=50000, # 命令输出最大字节数
env={
"PATH": f"{os.path.dirname(sys.executable)};{os.environ.get('PATH', '')}",
},
),
system_prompt='你是一个助手,请根据用户输入的指令,进行相应的操作。'
)
새로운 기능:
python script.py, ls -la)적용 시나리오:
DeepAgents의 강점은 그 확장성에 있습니다. 이를 통해BackendProtocol인터페이스를 통해 완전히 사용자 정의 가능한 Backend를 만들 수 있습니다:
from deepagents.backends.protocol import BackendProtocol, WriteResult, EditResult
from deepagents.backends.utils import FileInfo, GrepMatch
from datetime import datetime
import re
class DictBackend(BackendProtocol):
"""将文件存储在内存字典中的自定义后端"""
def __init__(self):
self.files = {} # 路径 -> 内容
self.metadata = {} # 路径 -> 元数据
def ls_info(self, path: str) -> list[FileInfo]:
"""列出文件和目录信息"""
result = []
seen_dirs = set()
for file_path in self.files.keys():
if file_path.startswith(path):
remaining = file_path[len(path):]
if '/' in remaining:
dir_name = path + remaining.split('/')[0] + '/'
if dir_name not in seen_dirs:
seen_dirs.add(dir_name)
result.append(FileInfo(path=dir_name, is_dir=True))
else:
meta = self.metadata.get(file_path, {})
result.append(FileInfo(
path=file_path,
is_dir=False,
size=meta.get('size', 0),
modified_at=meta.get('modified_at')
))
return result
def read(self, file_path: str, offset: int = 0, limit: int = 2000) -> str:
"""读取文件内容,支持分页"""
if file_path not in self.files:
return f"Error: File '{file_path}' not found"
content = self.files[file_path]
lines = content.splitlines(keepends=True)
start_line = offset
end_line = start_line + limit if limit > 0 else len(lines)
selected_lines = lines[start_line:end_line]
result = ''.join(f"{start_line + i + 1}: {line}" for i, line in enumerate(selected_lines))
return result if result else "(end of file)"
def write(self, file_path: str, content: str) -> WriteResult:
"""写入新文件(仅创建,不覆盖)"""
if file_path in self.files:
return WriteResult(error=f"File '{file_path}' already exists (create-only).")
self.files[file_path] = content
self.metadata[file_path] = {
'size': len(content),
'modified_at': datetime.now().isoformat()
}
return WriteResult(path=file_path, files_update=None)
def grep_raw(self, pattern: str, path: str | None = None, glob: str | None = None) -> list[GrepMatch] | str:
"""正则表达式搜索文件内容"""
try:
re.compile(pattern)
except re.error as e:
return f"Invalid regex pattern: {e}"
matches = []
for file_path, content in self.files.items():
for i, line in enumerate(content.splitlines()):
if re.search(pattern, line):
matches.append(GrepMatch(path=file_path, line=i+1, text=line))
return matches
def glob_info(self, pattern: str, path: str = "/") -> list[FileInfo]:
"""通配符匹配文件"""
import fnmatch
all_files = [
FileInfo(path=p, is_dir=False, size=self.metadata[p]['size'],
modified_at=self.metadata[p]['modified_at'])
for p in self.files.keys() if p.startswith(path)
]
matched = [fi for fi in all_files if fnmatch.fnmatch(fi.path, path.rstrip('/') + '/' + pattern)]
return matched
def edit(self, file_path: str, old_string: str, new_string: str, replace_all: bool = False) -> EditResult:
"""编辑文件内容"""
if file_path not in self.files:
return EditResult(error=f"File '{file_path}' not found")
content = self.files[file_path]
if replace_all:
new_content = content.replace(old_string, new_string)
occurrences = content.count(old_string)
else:
if content.count(old_string) != 1:
return EditResult(error=f"Found {content.count(old_string)} occurrences. For safety, edit requires exactly one match unless replace_all=True.")
new_content = content.replace(old_string, new_string, 1)
occurrences = 1
if new_content == content:
return EditResult(error=f"String '{old_string}' not found.")
self.files[file_path] = new_content
self.metadata[file_path]['size'] = len(new_content)
self.metadata[file_path]['modified_at'] = datetime.now().isoformat()
return EditResult(path=file_path, files_update=None, occurrences=occurrences)
사용자 지정 백엔드 사용:
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend, LocalShellBackend
from langgraph.checkpoint.memory import InMemorySaver
from my_backend import DictBackend
checkpointer = InMemorySaver()
agent = create_deep_agent(
model=llm,
tools=[web_search],
checkpointer=checkpointer,
backend=DictBackend(),
system_prompt='你是一个助手,请根据用户输入的指令,进行相应的操作。'
)
커스텀 백엔드의 장점:
| 시나리오 | 추천 백엔드 | 이유 |
|---|---|---|
| API 호출만 필요하며 파일 작업이 필요 없음 | 백엔드 없음 | 간단하고 효율적 |
| 지속적인 파일 저장이 필요함 | FilesystemBackend | 직접 디스크 파일 작업 |
| shell 명령 실행이 필요함 | LocalShellBackend | 명령 실행 및 파일 작업 지원 |
| 완전한 격리 또는 커스텀 저장이 필요함 | 사용자 정의 Backend | 유연하고 제어 가능하며 특수 요구 사항에 적합 |
Backend는 DeepAgents 프레임워크에서 AI Agent와 파일 시스템을 연결하는 다리입니다. 유연하게 선택하거나 커스터마이징한 Backend를 통해 우리는 Agent에게 안전하고 효율적이며 제어 가능한 파일 작업 환경을 제공할 수 있습니다. 단순한 Backend 구성 없이, 기능이 강력한 LocalShellBackend까지, 완전히 커스터마이징된 DictBackend까지 DeepAgents는 다양한 응용 시나리오를 만족시키기 위한 풍부한 옵션을 제공합니다.
Backend 사용법을 익히면 더욱 강력하고 실용적인 AI Agent를 구축할 수 있으며, 지능형 에이전트가 실제로 "动手" 능력을 갖추게 할 수 있습니다!
이 콘텐츠는 인셔셔RSS(RSS 리더)가 자동으로 집계한 것으로 읽기 참고용입니다. 원문 출처 — 저작권은 원저작자에게 있습니다.