Практические советы: обновите ваш Deep Agent с помощью локальной песочницы на основе открытого кода
Пошаговое руководство по практическим рекомендациям: обновите свой Deep Agent с помощью локальной песочницы на основе открытого кода: контракты, проверки и слоты для вставки кода для команд, использующих эту модель.
Используйте это как переработанную версию идей из статьи «Улучшите ваш Deep Agent с помощью локальной песочницы на открытом коде» для операторов: четкие этапы, упорядоченные блоки кода и записи о восстановлении, сохраняющиеся при передаче задач. Этап Обзора работает наилучшим образом, если рассматривать его как измеримую основу. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф.
Что такое песочница и почему агентам она нужна
На этапе «Что такое песочница?» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Внедрять утверждение человеком для тех случаев, когда происходит трата средств или изменение данных в продакшене. Наличие связей на этапе компиляции не гарантирует полноты функционала продукта.
Проблема
На этапе реализации необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не пытаясь угадать скрытое состояние системы. Лучше использовать небольшие, тестируемые модули вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной структурой обработки данных. Внедрять человеческое утверждение для операций, связанных с расходованием средств или изменением производственных данных. Простая настройка во время компиляции не гарантирует полноты функционала системы.
Войдите в OpenSandbox
На этапе Enter OpenSandbox необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия элементам, определите критерии успеха и не допускайте молчаливого частичного завершения задачи. Внедряйте человеческое утверждение для операций, связанных с тратой денег или изменением производственных данных. Компиляционная настройка не заменяет полного соответствия бизнес-требованиям. На этапе Enter OpenSandbox необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, которое операторы могут проверять, не читая весь кодовый граф.
Точка расширения среды тестирования Deep Agents
При работе над этапом расширения среды тестирования Deep Agents сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой список поможет сохранять честность последующих изменений в коде. Документируйте одновременно успешный и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Создавайте контрольные точки после дорогостоящих операций. Функция возобновления выполнения не должна повторно взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий узел.
class BaseSandbox(ABC):
def execute(self, command: str, *, timeout: int | None = None) -> ExecuteResponse: ...
@property
def id(self) -> str: ...
def upload_files(self, files: list[tuple[str, bytes]]) -> list[FileUploadResponse]: ...
def download_files(self, paths: list[str]) -> list[FileDownloadResponse]: ...
Создание интеграции
При работе над этапом создания интеграции сначала запишите условия контракта: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые модули большим скриптам. Если какой-то шаг не сработает, причина неудачи должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Вносите контрольные точки после дорогостоящих шагов. Система возобновления работы не должна повторно взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий элемент цепочки.
Как работает OpenSandbox?
При работе над этапом «Как работает OpenSandbox» сначала запишите контракт: необходимые входные данные, сигнал о успехе и что происходит при частичной неудаче. Такой чек-лист помогает сохранять честность последующих изменений в коде. Рассматривайте этот этап как контракт между входными данными и проверенными выходными данными. Дайте названия результатам работы, определите критерии успеха и не допускайте безусловного частичного завершения задачи. Создавайте контрольные точки после дорогостоящих операций. Механизм возобновления работы не должен повторно оплачивать один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий этап. При работе над этапом «Как работает OpenSandbox» сначала запишите контракт: необходимые входные данные, сигнал о успехе и что происходит при частичной неудаче. Такой чек-лист помогает сохранять честность последующих изменений в коде. Храните конфигурацию отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код.
# Generate a starter config
uvx opensandbox-server init-config ~/.sandbox.toml --example docker
# Start the server
uvx opensandbox-server
Упрощенный код интеграции
Этап кода интеграции в упрощённой версии работает наилучшим образом, когда его рассматривают как измеримую структуру. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте одновременно успешный и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки. Сохраняйте структуру графа простой и типизированной. Вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
.create()
Этап создания работает наилучшим образом, если рассматривать его как измеримую структуру. Соберите один идеальный пример результата, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда происходит сбой, он должен указывать на конкретную ответственность, а не на запутанную цепочку операций. Сохраняйте структуру графа простой и типизированной. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
class MinimalOpenSandboxBackend(BaseSandbox):
def __init__(self, sandbox: Sandbox, runner: AsyncRunner):
self._sandbox = sandbox
self._runner = runner
from opensandbox import Sandbox
from opensandbox.config import ConnectionConfig
IMAGE = "opensandbox/code-interpreter:v1.1.0"
ENTRYPOINT = ["/opt/code-interpreter/code-interpreter.sh"]
@classmethod
def create(cls, api_key: str | None = None) -> "MinimalOpenSandboxBackend":
runner = AsyncRunner()
config = ConnectionConfig(domain="localhost:8080", api_key=api_key)
sandbox = runner.run(
Sandbox.create(IMAGE, entrypoint=ENTRYPOINT, connection_config=config, timeout=timedelta(minutes=30))
)
return cls(sandbox, runner)
.id()
Этот этап работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задачи. Сохраняйте структуру графа простой и типизированной. Вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, что приводит к нарушению возобновления работы после перерывов. Этот этап работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф.
@property
def id(self) -> str:
return self._sandbox.id
.execute()
На этапе выполнения необходимо заранее определить входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Внедрять утверждение человеком для операций, связанных с тратой денег или изменением производственных данных. Подключение компонентов во время компиляции не гарантирует полноты функционала продукта.
from deepagents.backends.protocol import ExecuteResponse
def execute(self, command: str, *, timeout: int | None = None) -> ExecuteResponse:
execution = self._runner.run(self._sandbox.commands.run(command))
stdout = "\n".join(c.text for c in execution.logs.stdout)
stderr = "\n".join(c.text for c in execution.logs.stderr)
output = "\n".join(p for p in (stdout, stderr) if p)
return ExecuteResponse(output=output, exit_code=execution.exit_code or 0)
.upload_files()
На этапе загрузки файлов необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние. Лучше использовать небольшие, тестируемые модули вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной структурой обработки данных. Внедрять утверждение человека там, где происходит расход средств или изменение данных в продакшене. Простая настройка во время компиляции не гарантирует полноты реализации бизнес-логики.
from opensandbox.models import WriteEntry
from deepagents.backends.protocol import FileUploadResponse
def upload_files(self, files: list[tuple[str, bytes]]) -> list[FileUploadResponse]:
entries = [WriteEntry(path=path, data=data, mode=644) for path, data in files]
try:
self._runner.run(self._sandbox.files.write_files(entries))
return [FileUploadResponse(path=p) for p, _ in files]
except Exception as exc:
return [FileUploadResponse(path=p, error=str(exc)) for p, _ in files]
.download_files()
На этапе загрузки файлов необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Укажите названия файлов, определите критерии успеха и не допускайте молчаливого частичного завершения работы. Внедряйте проверку человеком для операций, связанных с тратой денег или изменением производственных данных. Простая настройка во время компиляции не гарантирует полноты выполнения бизнес-задач.
from deepagents.backends.protocol import FileDownloadResponse
def download_files(self, paths: list[str]) -> list[FileDownloadResponse]:
results = []
for path in paths:
try:
content = self._runner.run(self._sandbox.files.read_bytes(path))
results.append(FileDownloadResponse(path=path, content=content))
except Exception as exc:
results.append(FileDownloadResponse(path=path, error=str(exc)))
return results
На этапе загрузки файлов необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код.
.kill()
При работе с этапом остановки сначала необходимо зафиксировать условия работы: требуемые входные данные, сигнал успешного завершения и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Необходимо документировать как успешный, так и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не последующими улучшениями. Создавайте точки контроля после ресурсоемких шагов. Функция возобновления не должна повторно взимать плату за один и тот же вызов большой языковой модели при повторной попытке оператора выполнить последующий узел.
def kill(self) -> None:
self._runner.run(self._sandbox.kill())
self._runner.shutdown()
Мост синхронизации/асинхронности
При работе над этапом «Мост синхронизации/асинхронности» сначала запишите контракт: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг терпит неудачу, причина должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Вносите контрольные точки после дорогостоящих шагов. Механизм возобновления работы не должен повторно запрашивать один и тот же вызов LLM, когда оператор пытается выполнить следующий узел.
Агент анализа данных в песочнице
При работе над этапом агента анализа данных A сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия создаваемым элементам, определите критерии успешности и не допускайте безусловного частичного завершения работы. Выполняйте контрольные точки после дорогостоящих операций. Система возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить последующий этап. При работе над этапом агента анализа данных A сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код.
import asyncio
import nest_asyncio
import threading
from datetime import timedelta
from pathlib import Path
from deepagents import create_deep_agent
from deepagents.backends.protocol import ExecuteResponse, FileDownloadResponse, FileUploadResponse
from deepagents.backends.sandbox import BaseSandbox
from langchain.chat_models import init_chat_model
from opensandbox import Sandbox
from opensandbox.config import ConnectionConfig
from opensandbox.models import WriteEntry
# nest_asyncio for running async functions in Jupyter.
nest_asyncio.apply()
IMAGE = "opensandbox/code-interpreter:v1.1.0"
ENTRYPOINT = ["/opt/code-interpreter/code-interpreter.sh"]
backend = MinimalOpenSandboxBackend.create(api_key="SANDBOX_API_KEY")
print("Sandbox ready:", backend.id)
llm = init_chat_model(
model="gemini-3.5-flash",
model_provider="google_genai",
api_key=os.environ["GOOGLE_API_KEY"],
max_tokens=14750,
max_retries=5,
)
agent = create_deep_agent(
model=llm,
system_prompt=(
"You are a Python coding assistant with sandbox access. "
"You specialize in performing data analysis and data visualization with python,"
"you generate clear reports with good looking charts using seaborn."
),
backend=backend,
)
csv_bytes = Path("customers-1000.csv").read_bytes()
results = backend.upload_files([("/workspace/customers-1000.csv", csv_bytes)])
for r in results:
if r.error:
print(f"Upload failed for {r.path}: {r.error}")
else:
print(f"Uploaded {r.path}")
result = agent.invoke({
"messages": "Perform a deep exploratory data analysis on the customers-1000.csv file "
"and summarize the findings in a markdown report with clear charts."
})
# Deep Exploratory Data Analysis: Customer Acquisition and Profiling
**Dataset:** `customers-1000.csv`
**Analysis Period:** Jan 2020 – May 2022
---
## 1. Executive Summary
This report presents a comprehensive exploratory data analysis (EDA) of a customer database containing 1,000 unique records. The analysis delves into geographical distributions, sign-up temporal trends, domain & technical alignments, and name demographics to uncover actionable insights for strategic growth.
### Key Takeaways
1. **Unprecedented Global Reach:** The customer base is extraordinarily decentralized, spanning **240 countries** across all **7 continents** (including Antarctica). No single country represents more than 1.2% of the customer base. Africa (24.7%) and Asia (22.6%) are the leading regions, followed by Europe (18.5%) and North America (16.1%).
2. **Stable Acquisition Trends:** Customer subscriptions are remarkably stable, averaging roughly **34-35 new customers per month** across 2020 and 2021. This consistency is maintained across all continents year-over-year, indicating a highly standardized, globally distributed customer acquisition channel.
3. **Mid-Week and Weekend Consistency:** Subscriptions are evenly spread across the days of the week, with a minor peak on Friday and Saturday, and a minor trough on Thursday.
4. **B2B / Synthetic Profile Characteristics:** The dataset shows zero domain overlap between customer email domains and company websites (0.0% exact match across 923 unique domains). Combined with the near 1-to-1 ratio of customers to companies, this suggests a highly B2B-centric profile (one representative per enterprise) or synthetically generated profiles with randomized fields.
5. **Standardized TLD Footprint:** The `.com` top-level domain (TLD) dominates both emails (61.2%) and corporate websites (58.8%). The remaining distribution is evenly split among `.org`, `.net`, `.biz`, and `.info`.
---
## 2. Dataset Structure & Data Integrity
The initial dataset contains **1,000 rows** and **12 columns**. An inspection of data integrity reveals excellent completeness:
- **Zero Missing Values:** Every column is 100% populated.
- **Zero Duplicates:** There are no duplicate rows, and the `Customer Id` column contains 1,000 unique identifiers.
- **Data Types:** All columns are stored as object/string types except for `Index` (integer).
### Data Preprocessing & Feature Engineering
To enable deep exploratory analysis, several features were engineered:
1. **Temporal Features:** `Subscription Date` was parsed as a datetime object, allowing the extraction of `Sub_Year`, `Sub_Month`, `Sub_Month_Name`, `Sub_Day_of_Week`, and `Sub_Year_Month` (period).
2. **Geographical Mapping:** Using the `pycountry` and `pycountry-convert` libraries, coupled with a manual fallback dictionary for territories, each of the 240 countries was successfully mapped to its respective **Continent**.
3. **Domain & Technical Profiles:** Email domains (`Email_Domain`), email TLDs (`Email_TLD`), and website TLDs (`Website_TLD`) were extracted to analyze the technical profiling of users.
---
## 3. Geographical Analysis
### Continent-Level Distribution
The geographic reach of this customer base is truly global. Rather than being concentrated in a single dominant market like North America or Europe, customers are spread across all continents:
| Continent | Customer Count | Percentage |
| :--- | :---: | :---: |
| **Africa** | 247 | 24.7% |
| **Asia** | 226 | 22.6% |
| **Europe** | 185 | 18.5% |
| **North America** | 161 | 16.1% |
| **Oceania** | 107 | 10.7% |
| **South America** | 54 | 5.4% |
| **Antarctica** | 20 | 2.0% |
#### Chart 1: Customer Distribution by Continent

### Country-Level Distribution (Top 15 Countries)
The country-level distribution exhibits a heavy tail, with the 1,000 customers distributed across **240 distinct nations**. This indicates that the average number of customers per country is only **4.17**.
The top countries by customer density are:
- **Liechtenstein:** 12 customers (1.2%)
- **Gabon:** 10 customers (1.0%)
- **China, Bangladesh, Reunion, Nigeria, Luxembourg:** 9 customers each (0.9%)
This extreme dispersion suggests a borderless, digital-first product that appeals universally across jurisdictions without localized geographic bias.
#### Chart 2: Top 15 Countries by Customer Count

---
## 4. Temporal Analysis (Subscription Trends)
... (Trimmed to keep blog (estimated read time short))
От ноутбука к пакету PyPi
Процесс преобразования ноутбука в готовый продукт работает наилучшим образом, если рассматривать его как измеримую структуру. Сначала зафиксируйте один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию, прежде чем расширять объем работ. Документируйте как успешный, так и восстановительный пути выполнения. Повторные попытки, проверки со стороны людей и обработка некорректных сообщений являются частью продукта, а не этапом последующей доработки. Сохраняйте структуру графа простой и типизированной. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и могут нарушить возобновление работы после прерываний.
!pip install deepagents-opensandbox-backend
Посмотрите
Этап «Проверьте» работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг сбивается, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Сохраняйте структуру графа простой и типизированной. Вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
Чек-лист операционной работы
При работе над этапом чек-листа операционной работы сначала опишите условия использования: необходимые входные данные, сигнал о успешном выполнении и действия при частичном сбое. Такой чек-лист обеспечивает прозрачность последующих изменений в коде.
Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе от демо-среды к общедоступным средам.
Пункт контроля после дорогостоящих операций. Функция возобновления не должна снова взимать плату за один и тот же вызов LLM при повторной попытке обработки последующего узла оператором.
Закрепите версии зависимостей и запишите хэш изображения, с использованием которого выполнялась демонстрация. Воспроизводимость важнее устного опыта сотрудников.
Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф зависимостей.
Пункт контроля после дорогостоящих операций. Функция возобновления не должна снова взимать плату за один и тот же вызов LLM при повторной попытке обработки последующего узла оператором.
Перед переходом на новую версию стека заморозьте версии, сделайте полную запись процесса для критически важных этапов и убедитесь, что известны шаги возврата к предыдущей версии. В совместных средах необходимы ограничения на частоту запросов, проверки принадлежности ресурсов и четко определенный ответственный за обновление секретов. Лучше надежность, несмотря на ее простоту, чем красивые, но единоразовые демонстрации.
Примечание к пакету обновлений для 43662eb4f13d: не включайте ключи поставщиков в репозиторий, установите лимит токенов на одну сессию и храните транскрипции рядом с фиксами для оценки, чтобы последующие замены моделей оставались сопоставимыми.
При работе над этапом 0 записи по усилению безопасности сначала запишите условия работы: необходимые входные данные, сигнал успешного выполнения и последствия частичной неудачи. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Рассматривайте этот этап как договор между входными данными и проверенными выходными результатами. Дайте названия файлам, определите критерии успеха и не допускайте безусловного частичного завершения работы.
Деталь усиления безопасности 0/814: измерьте время выполнения, класс ошибки и расход токенов для данного примечания, затем решите, следует ли сохранять изменения на основе фиксированного набора критериев, а не на основе устных замечаний.