A year ago, Simon Willison wrote one of the cleanest definitions of an agent that has stuck around:

An LLM agent runs tools in a loop to achieve a goal.

That definition stuck because it describes what every production agent actually does. Kiro, Amazon Q Developer, Quick Agents, Codex, Claude Code: under the hood, they all run the same shape. The agent loop is the common denominator.

But the loop was never the hard part. The hard part was everything around it.

Pick a framework. Wire up tools. Provision sandboxed compute. Configure storage, secrets, networking. Decide where memory lives. Bolt on observability. Get the right dependencies into the right container. Also, local prototyping tends to be the easy part: a single developer can stand up an agent on their laptop in an afternoon. Getting it into production is where the work explodes, and the moment it has to serve more than one user, a whole new layer of work shows up: concurrency, isolation, identity, state, scaling.