Avoiding Monolithic AI Workflow Design: Better Structure for Custom Agents, Instructions, and Skills
When AI-assisted workflows start delivering value, the first version often grows in the wrong direction: one huge **Custom agent** with every rule, every step, and every edge case embedded inline. It works, until every small change becomes slow and starts breaking something unrelated.
This post is about structural mistakes to avoid, and a practical architecture that scales: thin orchestrator agents, focused **Skill** units, clear **Instructions**, and predictable output paths.
```mermaid
flowchart LR
A[Monolithic Custom agent<br/>Rules + logic + state + outputs]
B[Thin orchestrator Custom agent<br/>Sequencing + policy]
C[Focused Skill units<br/>Executable capabilities]
D[Scoped Instructions<br/>Standards by applyTo]
E[Stable output contracts]
F[Maintainable AI workflow]
A --> B
B --> C
B --> D
C --> E
D --> E
E --> F
style A fill:#ffd6d6
style B fill:#e1f5ff
style C fill:#f0e1ff
style D fill:#fff4e1
style E fill:#e1ffe1
style F fill:#e1ffe1
```
## 1. What goes wrong in monolithic agent design
In practice, many failures here are not model failures. They are boundary failures.
When one **Custom agent** owns orchestration, domain logic, schema shaping, state management, approval flow, and output formatting, each change becomes risky and expensive. A fix in one area quietly changes behavior somewhere else because too much is tied together.
**Key Characteristics:**
- **Coupled responsibilities**: A single file mixes policy, execution logic, and artifact contracts.
- **Low reusability**: Valuable capability cannot be invoked independently by other workflows.
- **High guardrail load**: The prompt grows more defensive because the structure is doing too little.
**Example:**
If scoring logic lives inline inside one agent, every workflow that needs scoring must re-run that whole workflow instead of invoking a reusable **Skill**.
## 2. Anti-patterns to avoid
These patterns are common in first-generation AI workflow repos and should be treated as structural debt.
| Anti-pattern | Why it fails over time |
|---|---|
| Monolithic **Custom agent** as the only execution unit | No modular reuse, hard to test, hard to evolve safely |
| Skills that contain specimen outputs instead of field contracts | Encourages copying examples instead of extracting real run data |
| Inconsistent naming and dispatch conventions | Increases cognitive load and onboarding friction |
| Divergent output paths between producers and consumers | Breaks reuse checks and forces people to regenerate work they already had |
| Mixing analysis with generation/approval workflows in one utility | Bloats scope and creates unnecessary safety complexity |
## 3. Clear role boundaries: who should own what
Good structure starts by assigning one responsibility per layer and enforcing it.
**Key Characteristics:**
- **Custom agent**: Should primarily own orchestration (phase order, tool access, run policy, result handling).
- **Skill**: Should primarily own capability logic (inputs, steps, outputs, success criteria).
- **Instructions**: Should define standards (coding, naming, output conventions by `applyTo`).
- **MCP server**: Should provide external system access (runtime data, APIs, stores).
**Example:**
A workflow agent decides sequence and policy. It delegates extraction, scoring, and reporting to distinct **Skill** units. Standards for output format and file layout remain in **Instructions**, not copied into every skill.
## 4. The impact of getting the boundaries wrong
Bad boundaries do not stay contained inside agent files. They show up in team speed, review quality, and confidence in the workflow.
**Common Impacts:**
- **Slower changes**: Small fixes require editing large prompts or orchestration blocks, so safe iteration turns into careful, infrequent releases.
- **Regression-heavy maintenance**: The same file decides too many things at once, so bug fixes often change output structure, routing, or approval behavior by accident.
- **Weak reuse**: Teams rebuild the same extraction or scoring logic in multiple places because the useful part was never extracted into a reusable **Skill**.
- **Noisy reviews**: Reviewers end up parsing long prose blobs instead of inspecting a narrow capability contract or a specific orchestration decision.
- **Harder incident response**: When output quality drops, it is unclear whether the cause lives in instructions, tool access, orchestration order, or embedded business logic.
- **Lower confidence**: Once runs feel unpredictable, teams add more guardrail text instead of fixing structure, which usually makes the workflow harder to review and no more reliable.
**Example:**
If one agent both pulls runtime data, interprets it, applies policy, and writes final artifacts, a bad result gives you nowhere obvious to start. The team cannot tell whether the failure came from data retrieval, capability logic, or orchestration policy without reading and re-running the whole thing.
## 5. Design principles that prevent drift
The difference between a stable system and a fragile one is usually a handful of explicit contracts.
1. **Contract-first skills**: Define typed output fields and required inputs; avoid canned "example result" payloads in operational extraction prompts.
2. **Single output root per workflow family**: Producers and consumers should resolve the same artifact paths.
3. **Consistent naming**: Standardize file suffixes and dispatch style across all agents.
4. **Narrow utility scope**: Keep analysis utilities analysis-only; split generation/approval into separate utilities.
5. **Policy in one place**: Keep run-safety and orchestration policy in agents, not duplicated in every skill.
## 6. A reference structure for mixed agent systems
This baseline layout keeps boundaries visible and enforceable.
```text
.github/
agents/
workflow-orchestrator.agent.md # sequencing + policy only
skills/
capability-a/SKILL.md # one capability, one contract
capability-b/SKILL.md
instructions/
output-standards.instructions.md # applyTo: artifact paths, naming, schemas
copilot-instructions.md # global rules
.vscode/
mcp.json # external system connectors
documentation/
extracted/
<workflow-name>/ # single canonical output root
```
## 7. Migration approach that works in real teams
Do not big-bang this refactor. Extract capability by capability while preserving output contracts.
1. Pull the highest-value inline logic into its own **Skill** first.
2. Replace specimen-style schemas with strict contracts and required fields.
3. Keep the **Custom agent** focused on orchestration as each extraction lands.
4. Unify naming and output paths before adding new capabilities.
5. Split non-core responsibilities into separate utilities once contracts are stable.
## Wrapping Up
Most AI workflow fragility is self-inflicted architecture debt. The wrong structural decision does not just make prompts ugly; it slows work down, hides failure causes, and makes the whole system harder to trust. Keep **Custom agents** thin, **Skill** units explicit, and **Instructions** authoritative. Good boundaries do more for quality and safety than another page of guardrails.
## References
- [GitHub Docs: About customizing GitHub Copilot responses](https://docs.github.com/en/copilot/concepts/prompting/response-customization)
- [GitHub Docs: Adding repository custom instructions for GitHub Copilot](https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/add-custom-instructions/add-repository-instructions)
Comments
Post a Comment