Introducing ctx.traits | ctx.companySkip to content<br>Like many working in this early era of AI-driven systems, I have struggled to find an approach to agents that feels satisfying. As models improve at problem-solving, the tools and approaches often feel like either a blind bet or an afterthought.Each new trend or pattern feels like another brute-force attempt to bargain with the model, hoping to make it predictable by force. These approaches tend to come with a long list of requirements and an implicit agreement to ignore their shortcomings, leaving me with the ongoing chore of babysitting and double-checking at multiple levels.The field has cycled through prompt engineering, context engineering, loop engineering and now graph engineering. Each comes with its own quirks and assumptions. The challenge is taking what works from each, without pretending productivity is improving when it is not.I am not claiming to have found the right approach, but the process has been gratifying, and the result feels like a step in the right direction for me.In the end, it came down to the same thing that has proven itself throughout my career: a careful balance between abstractions and the right interfaces, combined with the model’s ability to solve problems using the available tools.Prompt · Contract over prose<br>Here’s where things broke down fast: from the moment I started working with agents, stuffing everything into Markdown files full of prose was a trap. I kept trying to add structure, but it always turned into a constant slog of fighting the model, and an abstraction that never felt sturdy enough to rely on.It quickly became clear that putting too much logic into a text file and expecting an AI agent to interpret it as I would was not a good idea. Models struggled to follow all the instructions in a file and often tried to resolve contradictions on their own. Tracking organization and optimization through these crafted text files became a burden to test and maintain, especially across a team.This led to the first key decision: to construct instructions that are maintainable, testable, and declarative. They should be easy for agents to understand and for humans to reason about. My first attempt was a configuration-file approach, which at first felt similar to working with Terraform. It quickly proved too verbose and not enjoyable to use.This led me to implement a CDK-like solution that still targets a static configuration file as a synthesized contract. Defining the logic as code felt like the only sane path forward.export default trait("deep-refactor", {<br>version: "1.0.0",<br>name: "Deep Refactor",<br>summary: "Refactor the codebase to a more structured and maintainable state.",<br>metadata: {<br>tag: ["first-party", "refactoring", "review", "multi-agent"],<br>},<br>intent: {<br>require: [intent.BoundedRefinement, intent.PreserveOriginalBehavior],<br>avoid: [intent.InterfaceWidening, intent.UnboundedLoop],<br>block: [intent.StyleOnlyChange],<br>},<br>behavior: {<br>tone: [tone.Technical, tone.Direct],<br>verbosity: verbosity.Low,<br>method: method.EvidenceFirst,<br>},<br>});This declarative configuration makes the trait’s intent and expected behavior clear to agents. For humans, a quick look at the code should be enough to understand how the trait works and, more importantly, to maintain it with confidence. The aim is to make reasoning about the system straightforward.To learn more about metadata , intent or behavior , check the documentation.<br>Defining traits this way made it possible to automate more of the development process. Desired behaviors and instructions became extendable and composable, enabling the reuse of approaches across projects and avoiding copy-paste or prompt hacks.Context · Art of reveal and conceal<br>The next problem on my list was the one I had the most experience working with and trying different approaches to. Approaches discovered so far all sounded like great ideas on paper, formed around how individuals approach working with problems, but all lacking in either ergonomics or the confidence with which their outcomes can be trusted:Swarm agents - where you state the problem and delegate the work to a group of agents, aiming to reduce multiple opinions into one broad-view solutionPer-task compaction - where you work on a single problem within a single window of context, compacting afterward, hoping to “regain” the model’s intelligence, while keeping the high-level context of the projectAutomatic compaction - where you’re constantly working with a seemingly “infinite” window of context, hoping that the agent is smart enough to compress the knowledge for eternity and make it “permanent”Handoff - where you’re working with a single agent (e.g., planner) and hand over its definition of the problem to a different agent (e.g., worker) to actually implement itAfter spending considerable time with these approaches, I have concluded that careful handling of context is essential. This often lets me work around imperfect abstractions and lets the models do...