Skip to content

fix: Add resource cleanup mechanism in CodeAgent #1056

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/smolagents/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -1278,3 +1278,14 @@ def to_dict(self) -> dict[str, Any]:
agent_dict["executor_kwargs"] = self.executor_kwargs
agent_dict["max_print_outputs_length"] = self.max_print_outputs_length
return agent_dict

def cleanup(self):
"""Clean up resources used by the agent, especially Docker container resources."""
try:
self.python_executor.delete()
except AttributeError:
pass

def __del__(self):
"""Ensure resources are cleaned up when the agent is garbage collected."""
self.cleanup()
29 changes: 29 additions & 0 deletions tests/test_agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,35 @@ def fake_model(messages, stop_sequences):
assert len(agent.memory.steps) == 2
assert "Generation failed" in str(e)

@pytest.mark.require_run_all
def test_codeagent_cleanup_releases_docker_resources(self):
"""Test if CodeAgent properly releases Docker resources when cleanup is called"""
# Create a simple model
model = MagicMock()
model.return_value = ChatMessage(role="assistant", content="```python\nprint('Hello, World!')\n```")

import docker

# Create Docker client
client = docker.from_env()

# Create CodeAgent with docker as executor
agent = CodeAgent(tools=[], model=model, executor_type="docker")

# Get container ID
container_id = agent.python_executor.container.id

# Verify container is running
containers = [c.id for c in client.containers.list()]
assert container_id in containers, "Container should be created and running"

# Directly call cleanup method instead of relying on garbage collection
agent.cleanup()

# Verify container has been removed
containers = [c.id for c in client.containers.list(all=True)]
assert container_id not in containers, "Docker container should be removed when CodeAgent.cleanup() is called"


class CustomFinalAnswerTool(FinalAnswerTool):
def forward(self, answer) -> str:
Expand Down