Composing reusable AI workflows

An AI workflow often starts with a set of instructions for one task. You explain how to review a pull request or investigate an issue, try it out, and refine the instructions as you learn what works.

As you add more workflows, familiar steps start appearing. Several need to understand the code, follow the same conventions or run tests. Copying instructions works at first, but every improvement then means updating several places.

In my raholsn plugin, I keep those shared instructions in reusable skills. Different workflows can use the same review procedure, call on an agent for a focused task or run a script for a repeatable operation.

The other posts in this series explain individual workflows. This one looks at how those pieces fit together.

Three workflows connected to shared instruction cards, focused role cards and a tray of reusable tools

Give each part a clear job

A workflow needs instructions, but it may also need someone to review a change or a tool to look up information. I give each of those jobs a place in the plugin.

The examples here use Claude Code. The same approach can work in other tools, though their configuration will differ.

These are the main pieces in my plugin:

PartPurposeExample
User-facing skillCoordinates a task I ask the assistant to performwork, code-review, rabbitmq
Reference skillSupplies a shared procedure or supporting guidanceref-review-loop, ref-build-and-test
AgentHandles a focused assignment with its own role and contextarchitect, functional-reviewer, qa
Profile and company guidanceSupply the context that varies between workplacesTracker settings, engineering conventions
MCP connectionExposes external tools and data to the assistantElastic, Linear, SQL Server
LSP configurationMakes language-server support availableC#, Terraform, YAML
Bundled scriptImplements a repeatable local operationget-deploy-status.sh

The plugin keeps these pieces together so I can maintain and install them as a group.

What I mean by a reference skill

Testing is a good example of a step that several workflows need. Instead of repeating the testing instructions, I put them in a skill that each workflow can refer to.

I call these reference skills and give them a ref- prefix. Some describe a procedure; others contain shared guidance, such as company conventions. I normally use them through another workflow rather than invoke them myself.

For example, ref-build-and-test describes how to prepare for the selected checks, run them, handle cleanup and report the result. work uses it during implementation. fix-comments can use it after changing code, and the review loop uses it by default to validate fixes.

When I improve those testing instructions, all three workflows can use the change.

In this Claude Code implementation, the reference files use:

user-invocable: false
disable-model-invocation: false

The first hides the skill from the slash-command menu; the second leaves it available to the model. The rule that it should only be used when another workflow references it is expressed in the instructions. These flags alone do not enforce that caller relationship. The skill invocation documentation explains the distinction.

A skill can delegate to an agent

Some steps benefit from a separate reviewer. A workflow can ask an architect agent to examine a proposed change, then use its feedback to decide what to do next.

The reference skill explains what to send to that agent and what feedback to expect. The agent performs the review.

For example, ref-architect-review passes the task brief and relevant source or diff to the architect agent. The agent examines boundaries, contracts, concurrency and failure behavior, then writes architectural feedback. The calling workflow decides how to apply that feedback.

The same agent can review a plan before implementation or examine the code in an existing PR.

Other agents bring different perspectives. The functional reviewer checks whether the change does what the user needs. QA looks at how it has been tested. A workflow can choose the reviewers that fit the task.

Agents also need shared context. Several of mine preload ref-company-conventions and ref-company-testing through their skills frontmatter. I configure the current company’s guidance directly in those shared references. That is context supplied to the agent, rather than another agent being launched. Claude Code documents these preloads in its subagent configuration reference.

Reuse the review step in two different workflows

I want code reviewed both while an agent implements a feature and when I ask for a standalone PR review. The review procedure is similar, but what happens after the feedback is different.

During implementation, work can ask for a review, address supported findings, validate the fixes and review again when the changes warrant it. A standalone code-review request needs findings about the supplied PR; it should not begin modifying that change as part of the review.

Both use ref-review-loop, with an explicit mode:

CallerModeResult
workloopReview, address findings, validate changes and repeat when useful
code-reviewsingle-passReview once and return findings

Each workflow tells the review step which changes to examine, which reviewer to use and where to save the feedback. By default, it uses the functional reviewer and the shared testing instructions.

Those details matter. For a PR review, the reviewer needs the PR's changes, which may differ from the code currently checked out locally.

This simplified diagram shows those relationships. Arrows identify dependencies, not the order of every action in a run.

Work and code review share a review procedure, which delegates to a functional reviewer and uses validation after loop-mode fixes

Open the review example at full size

For this to work, the reviewer needs a clear task brief and a known place to write its feedback. The workflow can then read that feedback and continue.

Commands can compose other commands too

A queue investigation may lead to a question about application logs. The RabbitMQ workflow can call the logs workflow to follow that lead, provided it has relevant identifiers and a configured log connection.

The logs skill already describes how to search and connect log entries. Reusing it saves me from maintaining those instructions inside the RabbitMQ skill too.

Some relationships are simply handoffs between tasks. The planning sequence is:

grill-me-pragmatic → write-requirements → plan-implementation → work

I choose when to move between these stages. Writing requirements does not automatically create issues or start implementation.

The tools folder handles repeatable operations

Some tasks are predictable enough to put in a script. Looking up a deployment result, for example, does not need a fresh approach every time. The plugin keeps these scripts under tools/.

For example, get-deploy-status resolves the repository, workflow and job filter, then passes them to get-deploy-status.sh. The script reads GitHub Actions results and returns statuses and links. It does not establish live application health.

The skill works out what the user is asking for and passes the right arguments. The script does the lookup. I can improve the script without changing the skill, as long as its inputs and outputs stay the same.

MCP and LSP provide capabilities

Instructions alone cannot read a ticket or query application logs. The assistant needs access to tools that can do those things. My plugin configures MCP connections for Elastic, Linear and SQL Server in .mcp.json.

A connection still needs the appropriate endpoint, authentication and permissions. Declaring it in the plugin does not establish access. The workflow decides which available tools are relevant to the request and what to do with their results.

Language servers can also help with code navigation and diagnostics. My .lsp.json configures them for C#, Terraform and YAML. I do not use this part much yet, and the available features depend on the host and installed server.

This setup still has practical portability work left. The current C# configuration contains machine-specific paths, and the configured language-server binaries need to be installed. Packaging the configuration is only part of making it usable elsewhere. The Claude Code plugin reference describes the MCP and LSP integration points.

Keep workplace context separate

In Making skills useful across workplaces, I described using a profile and optional company pack for settings and guidance that change between companies.

Several agents need to follow the same company conventions. I put those conventions and testing guidance in shared reference skills, which the architect, planner and functional reviewer all use. When I move to another company, I can update the guidance in one place.

I configure the guidance directly in those references. External documents can override it when useful, but a separate company pack is optional. This keeps workplace guidance separate from the instructions for running a review or implementing a feature.

Use the dependency map when changing shared behavior

Changing a shared skill can affect several workflows. Before changing the review loop, for example, I need to check how both implementation and standalone reviews use it.

The chart below helps me find those connections. It comes from docs/command-dependencies.md and shows which parts use each other, rather than the steps taken during a particular run.

Explore the full plugin dependency map

Arrows point from callers to their dependencies. Thick arrows connect commands; solid arrows show reference use or agent delegation. Dashed agent arrows show preloaded context, and the naming-only reference from work is explicitly labelled. Conditional labels explain when a relationship applies. Configured domain reviewers sit outside the fixed set of bundled agents.

The chart is large; open the full-size version to inspect individual connections.

Full source dependency map of the raholsn plugin's commands, reference skills, agents and bundled script commands

Open the full dependency map

Download the Mermaid source

If I change the feedback format, I check both the agent that writes it and the workflow that reads it. I also update the map when those connections change.

Not every instruction needs its own file. I extract a shared skill when several workflows need it and its job is easy to explain. Splitting things further can make the workflow harder to follow.

The plugin and dependency guide

You can find my plugin and the command dependency guide on GitHub.

I built it this way so that improving one workflow can help the others too. A better testing procedure or review step becomes something I can reuse the next time I add a workflow.

Happy coding!

Please share
𝕏fin✉●☏➤LINEt▾Iw✎