20 November 2025 / AI agents

What I want from an always-on AI agent

I want an always-on agent to work like a worker with a job ticket: it takes a named job, leaves a record of what it did and puts any proposed change somewhere I can review it.

An arched modern office building with repeating horizontal window bands.
Photo: Joel Filipe (opens in a new tab)

I don't want an always-on agent waking up with a general instruction to be useful. I want it to get a job with an ID, an objective, input references, the tools it's allowed to use, a time limit and a completion condition. "Review these open issues and draft a prioritised note" tells it what to read and what to produce. "Keep the project moving" leaves it to decide what matters and how much authority it has, which is exactly what I don't want a background process deciding. Inputs should be references (a file path, an issue ID, a database key) so the run can record which version it actually read. And jobs need an expiry, because a daily summary that starts two days late should fail as stale instead of turning up looking current.

Each job should move through named states: queued, claimed, running, waiting for approval, completed, failed or cancelled. Claiming has to be atomic so two workers don't do the same job, and if a worker disappears and another one takes over through a lease, that's a new run, not the old one carrying on. Retries depend on the error. A network timeout might be worth another go, but a rejected permission request probably isn't, so I'd attach retry policy to the error class and send anything that needs a person to a dead-letter state.

Tools should be narrow for the job in front of it. A research job gets read access to named sources and somewhere to write a draft, and it has no business holding deployment credentials. "Read repository A" is a lot easier to review than a token that can read every repo the account can see, and where an integration can't issue narrow credentials, the wrapper should enforce an allowlist and log the resolved target before running anything. Write tools should use dry runs, drafts or sandboxes where they exist, so the worker can stop after preparing the change.

That proposed change belongs somewhere I can inspect it, not in a final chat message. For code it's a branch and diff, for config a patch, for data a dry-run report with affected IDs and counts. The review view should show the original job, the inputs used, the change, the checks run and anything unresolved. Approval should be tied to that exact artefact through a commit hash or patch checksum, so if the branch moves after I've looked at it, the approval doesn't count any more and the apply step checks it's using the version I reviewed.

Every run should record timestamps, state changes, tool calls, approvals, output references and a final status, plus the instruction and tool config versions it ran with. A tool returning success is one event; if the job changed an external record, the worker should read it back before calling it done. I also want hard limits (runtime, tool calls, budget, retries) that end in a stopped state with partial output, and a global switch that stops new claims without me killing a process halfway through a write. The first test I'd run is read-only: submit one job, watch it go through every expected state, check its source and output references, then restart the worker and make sure it doesn't claim the finished job again.

An agent that wakes up with a general instruction to be useful isn't something I'd leave running unattended. What I'm after is a worker that takes a named job with only the tools that job needs, stops at a change I can review and leaves a run record I can check against what actually happened. Before I'd let one run unattended, I'd want that first read-only job to pass through every expected state and the restart test to come back without a second claim.

Got a take on this?

Share it on X. I read the replies.

All blogs