Designing instructions for agents: skills, hooks and context hierarchies
The emergence of AI-native development as a discipline brought a productive paradox. Tools like Claude Code, GitHub Copilot and Cursor transformed the code writing cycle, but the quality of human-agent collaboration depends more on instruction architecture than on raw model capabilities. An agent with poorly structured context produces inconsistent results even with the most capable model. An agent with well-designed instructions, clear context hierarchy and correct lifecycle hooks transforms mediocre models into reliable engineering assistants.
The instruction hierarchy in GitHub Copilot is defined by three application levels. The first level is global instructions in .github/copilot-instructions.md: applied to all files in the workspace regardless of path. The second level is specific instructions in .github/instructions/*.instructions.md: each file can have frontmatter with applyTo: '**/*.tsx' or applyTo: 'src/components/**' that restricts application by glob pattern. The third level is session instructions explicitly transmitted via context. Overlap between levels is additive — more specific level instructions complement global ones rather than replacing them.
The CLAUDE.md file fulfills a different function in Claude Code. It is the project contract: describes architecture, code conventions, environment variables, development scripts, test commands and design decisions the agent must respect. The difference between an effective and an ineffective CLAUDE.md is not length — it is specificity. "Use TypeScript strict mode" is a generic instruction any agent would already apply. "Never use any — use unknown with type guards; imports ordered category → libs → components → lib → types; named exports preferred over default" is an actionable instruction that discriminates between implementation options.
The AGENTS.md file solves a different problem: multi-agent coordination. In workspaces with multiple projects and contexts, AGENTS.md functions as a project map — defines which projects exist, which agents are available, what skills each agent masters, and how the orchestrator should route tasks. A project in the Neuro-Symbolic Context Engine, for example, describes @architect, @implementer and @reviewer agents with explicitly separated domains. The @architect plans and delegates. The @implementer writes code with self-healing loops. The @reviewer validates quality. This separation is not semantic — it instructs the orchestrating agent on how to distribute sub-tasks when receiving a high-level instruction.
Skills are domain knowledge packages encapsulated in SKILL.md files. Each skill has frontmatter defining name, description (which serves as trigger for the agent to decide when to invoke) and optional applyTo for file-scoped context. The SKILL.md body contains domain rules, implementation patterns, examples and anti-patterns specific to that specialty. The difference between an effective skill and ineffective documentation is the density of operational instruction relative to explanatory text. A security skill that lists "avoid SQL injection" without explaining how to detect and fix the specific pattern in the project context has near-zero utility for the agent.
Lifecycle hooks control when and how context is automatically injected. The SessionStart hook executes when an agent session starts — ideal for pre-loading static context like project architecture, available environment variables and current repository state. The PostToolUse hook executes after each tool call — useful for observing results and injecting corrective context if the tool produced an error or unexpected result. The pre-commit hook validates changes before commit — runs tsc, linters and tests in a standardized way without depending on the agent remembering to do so.
The Neuro-Symbolic Context Engine implements an abstraction layer over this hierarchy. Instead of manually managing dozens of instruction files distributed across the workspace, the Engine maintains a structured knowledge base with projects, contexts, agents and skills. In the initial session, the SessionStart hook invokes smart_init which detects the workspace, loads relevant contexts with calibrated depth (summary vs full), injects instructions via auto-generated copilot-instructions.md and AGENTS.md, and presents a pre-loaded digest in the session context. This eliminates the "search-then-load" latency that degrades the first interaction of sessions without pre-warming.
Self-healing is the mechanism that makes the agentic loop robust. Claude Code implements this as: after each code change, run tsc --noEmit for type checking. If errors, analyze each error with file context and attempt correction — maximum 3 cycles before escalating to the user. The explicit protocol prevents both agents that stop at the first error and agents that enter infinite retry loops. The specification of maximum cycles is part of the skill instruction — it is not a default agent behavior, it is a domain rule that the self-healing skill defines.
Evaluating the quality of agent instructions follows concrete technical criteria. Specificity: does the instruction discriminate between at least two implementation options? Actionability: can the agent verify whether the instruction was followed without ambiguity? Scope: is the instruction correctly restricted to the context where it is relevant? Hierarchy: are contradictory instructions resolved by explicit precedence? Granularity: is the instruction so granular that the agent ignores it as trivial, or so abstract that it produces unwanted variation? The optimal space is medium-granular instruction: specific enough to discriminate implementations, abstract enough to cover legitimate problem variations.
AI-native systems architects who ignore instruction discipline eventually encounter the same problem as software architects who ignore API design discipline: systems that function at the demonstration level but fail at the production level. The difference between a demonstration agent and a production agent is not the model. It is the quality of the structured context that defines what the agent can know, how it should behave and what the success criteria are in each task domain.
