Agent Fatigue
There are lots of agent harnesses out there at the moment. I started with Amp, then switched to Copilot CLI. After that, and in between, I used OpenCode, which I am now stuck with after trying Codex. None of those are particularly complicated agent harnesses, but all of these applications have their own bugs, settings, workflows, and permission systems. Let’s take Amp and OpenCode.
Amp had its own permission settings in settings.json under the key permissions, but now it uses
regex patterns in a JavaScript plugin. That looks like this:
import type { PluginAIAskResult, PluginAPI } from "@ampcode/plugin";
/**
* Plugin that prevents risky git operations by asking the user for confirmation.
* Uses amp.ai.ask() to classify git commands as risky and prompts the user accordingly.
*/
export default function (amp: PluginAPI) {
const safePatterns = [
/^\s*git\s+status\b/,
/^\s*git\s+log\b/,
/^\s*git\s+diff\b/,
/^\s*git\s+show\b/,
/^\s*git\s+branch\s*$/,
/^\s*git\s+branch\s+-[av]\b/,
/^\s*git\s+stash\s+list\b/,
/^\s*git\s+remote\s+-v\b/,
/^\s*git\s+fetch\b/,
/^\s*git\s+pull\b/,
/^\s*git\s+add\b/,
/^\s*git\s+commit\b/,
/^\s*git\s+push\b(?!.*(-f|--force))/,
];
amp.on("tool.call", async (event, ctx) => {
const shellCommand = amp.helpers.shellCommandFromToolCall(event);
if (!shellCommand?.command) {
return { action: "allow" };
}
const command = shellCommand.command;
if (!/^\s*git\s+/.test(command)) {
return { action: "allow" };
}
if (safePatterns.some((pattern) => pattern.test(command))) {
return { action: "allow" };
}
const aiResponse: PluginAIAskResult = await ctx.ai.ask(
`Does this git command look like a potentially destructive operation that could lose work? Answer yes if it's a destructive operation like force push, branch deletion, reset, or checkout to detached HEAD. Command: ${command}`,
);
if (aiResponse.result === "no") {
return { action: "allow" };
}
const confirmed = await ctx.ui.confirm({
title: "Potentially destructive git operation",
message: `${command}\n\nReason: ${aiResponse.reason}\n\nDo you want to proceed?`,
confirmButtonText: "Allow",
});
if (confirmed) {
return { action: "allow" };
}
return {
action: "reject-and-continue",
message: `User cancelled potentially destructive git operation: ${command}`,
};
});
}
Stolen from the Amp Documentation
Whereas OpenCode has the permission settings in the opencode.json config file, which looks like this:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask",
"todowrite": "allow",
"grep": "allow",
"glob": "allow"
}
}
Well, Codex has something else in TOML, which is similar to OpenCode.
But the point is that I don’t want to care about the permission API, a vital part of the agent, for every model that I use. I want to have this in one place. Especially if the default is basically “Mr. Agent do everything you want download some packages”.
I have had enough for now. I will just use OpenCode and keep my very fine-grained permissions evolving, in the hope that I can use OpenCode everywhere I use agents with every model that I have access to.
I don’t get why every company is creating its own harness instead of focusing on its main business objective: the large language model. OpenCode and some other coding tools prove that you don’t need Codex or Claude Code to get the most out of your model. Why not just have a shared interface? I don’t get it! It is a waste of time.
Software quality is taking a toll at the moment anyway, but that is for another very opinionated piece of writing in the future!