Most AI tools focus on writing new code, but up to 80% of the cost of software comes from maintenance. What if an intelligent agent could handle that burden for you?
In this article, I’ll walk through an autonomous agent called dependency-director that handles one of the most common maintenance scenarios: dependency updates. It goes beyond merging dependency updates that are passing tests; it upgrades your code to match changes in the dependency. This provides a sneak peek into the future of automated engineering workflows.
Note: dependency-director is an experimental proof of concept and is not intended for production environments. Although it uses security guardrails like sandboxing and command filters, running LLM-generated code dynamically always involves security trade-offs. If you experiment with the code on GitHub, please do so in an isolated testing environment, start with the --dry-run flag, and use highly restricted API tokens.
Loop engineering for software updates
A continuous triage loop is at the center of the process. The agent scans repositories and maps every open pull request to a state and triggers an action.
When a dependency update breaks a test suite, the agent automatically clones the repository and updates the code to align with the updated dependency.
Dependency Director runs on the Google Antigravity SDK, with Gemini taking care of the reasoning. You can configure the agent like this (full version in main.py):
config = LocalAgentConfig(
model="gemini-3.5-flash",
system_instructions=system_instructions,
policies=policies,
tools=agent_tools, # 12 GitHub API tools, plus a sandboxed shell
workspaces=[project_root, workspace_tmp],
capabilities=types.CapabilitiesConfig(
enable_subagents=False,
disabled_tools=[types.BuiltinTools.RUN_COMMAND],
),
)
Two lines do most of the security work. disabled_tools=[types.BuiltinTools.RUN_COMMAND] turns off the SDK’s built-in shell, so the only way the agent can run a command is through my sandboxed wrapper. And workspaces pins file operations to the project directory and a per-repo temp workspace, so the agent can’t wander through the filesystem.
Guardrails live in the tools, not the prompt
A common mistake in agent design is writing rules into the system prompt and hoping the model follows them. All important constraints are enforced in the tool functions themselves.
For example, the author of the pull request must be one of the allowed bots. The defaults are dependabot[bot] and renovate[bot].
def _check_bot_author(author: str, bots: list[BotConfig]) -> BotConfig:
allowed = {b.author for b in bots}
if author not in allowed:
raise PermissionError(
f"Security Block: Only pull requests authored by {allowed} "
f"can be processed. This PR was authored by '{author}'."
)
return next(b for b in bots if b.author == author)
There’s also a --dry-run parameter, so that you can simulate the behavior locally, without updating the pull request.
async def merge_bot_pr(owner: str, repo: str, pr_number: int) -> str:
author = await client.get_pr_author(owner, repo, pr_number)
_check_bot_author(author, bots)
if dry_run:
return f"[DRY-RUN] Would have merged PR #{pr_number} in {owner}/{repo}."
All fixes are held up as an open PR for your review by default, unless you use --automerge.
Patching a red pull request
When a PR has a conflict, the agent follows a procedure in its system instructions located in instructions.py. It uses the code-review-and-quality skill from Addy Osmani to go beyond just making the test pass, and ensure a code review and quality standards are enforced:
RED: Retrieve logs via 'get_pr_workflow_run_logs'. Clone into a subdirectory,
then check out the PR branch:
git fetch origin pull/<pr_number>/head:pr-<pr_number> && git checkout pr-<pr_number>
Otherwise install deps, test, fix, verify, and push to the remote branch.
Max 3 fix attempts per RED PR before skipping.
Run 'code-review-and-quality' self-review before committing.
The agent is also very clear about what counts as a fix. It’s told to consider what’s changed in the API documentation, and not just chase a green checkmark:
- Fix root causes (types, signatures, API changes) using changelogs.
- NEVER suppress errors (type: ignore, noqa, Any) unless upstream bugs
leave no alternative (require comment).
Running untrusted code in a sandbox
To restrict filesystem and network operations, Dependency Director uses sandbox-runtime. It’s an open-source OS-level sandbox. Every shell command the agent runs is wrapped in it:
process = await asyncio.create_subprocess_exec(
"srt", "--settings", active_config_path, "-c", command_line,
cwd=target_cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env,
)
You can configure the settings file where the sandbox is configured. The default settings allow network access to package registry domains such as PyPI, npm, crates.io. The agent is blocked from reading the home directory and writing to the .env environment variable file and .git/hooks. Here’s the bundled srt-settings.json, trimmed to a few representative entries:
{
"network": {
"allowedDomains": ["github.com", "pypi.org", "registry.npmjs.org"],
"deniedDomains": ["*.ngrok.io", "*.webhook.site", "*.requestbin.com"]
},
"filesystem": {
"denyRead": ["~"],
"allowWrite": ["/tmp"],
"denyWrite": [".env", ".git/hooks"],
"allowGitConfig": false
}
}
Trying it out yourself
Solid test coverage is essential for updating dependencies. Tests give you the confidence to know that your code still functions. When you use Dependency Director, they’re absolutely required so that the agent can safely patch your code to work with the updated dependencies. For tips on effective tests, see my blog post on five essential testing patterns.
Using an AI agent does consume tokens, of course. I performed a trial run on a repo with 6 open pull requests using gemini-3.5-flash. It used about 200k tokens. At the current published rate, that’s about $0.30 USD for the run, or roughly 6 cents per PR.
The code to try out dependency-director is on GitHub for you to try. Start with --dry-run to see how it works for you!
What maintenance work would you hand to an agent first? Tell me on X, LinkedIn, or Bluesky.

Top comments (0)