npx skills add ...
npx skills add mulesoft/mulesoft-dx --skill build-agent-broker-project
Build, edit, validate, publish, and deploy a MuleSoft Agent Broker (Agent Network V2) project end-to-end. Use whenever the user asks to build, create, scaffold, configure, edit, validate, publish, or deploy an Agent Broker, agent network V2, AgentScript, `.agent` file, or `agentNetwork: 2.0.0` project. Do NOT trigger for V1→V2 migration (use the converter skill).
npx skills add mulesoft/mulesoft-dx --skill build-agent-broker-project
You MUST output ≤ 4 lines of user-facing text per turn, unless you are emitting a numbered list of confirmed items (asset list, validation findings, asset → node assignments) — in which case the list itself is the output and gets no preamble.
FORBIDDEN openings. Never start a turn with any of these phrases or their synonyms. If you catch yourself typing one, delete it:
FORBIDDEN content. Never include in a turn:
REQUIRED shape of a normal turn:
End-of-phase confirmation shape:
Validation-result shape:
If a phase needs multiple actions, do them in tool calls without narrating between them. Only emit user-facing text at decision/confirmation points.
Turns a natural-language description of a multi-agent workflow into a complete, validated, deployable Agent Network V2 (GA, A2A v1.0) project. Runs a 6-phase guided experience and adds publish + deploy.
The skill is CLI-first end-to-end. Validate/publish/deploy use the Anypoint CLI Agent Fabric plugin (mulesoft-anypoint-cli-agent-fabric-plugin). Exchange asset search uses Anypoint CLI v4 (anypoint-cli-v4 exchange asset list). Both are portable across Claude Code, Cursor, Codex, and Vibes, and match the CI/CD path. MCP tools (mcp__mulesoft__*) work as a fallback when present, but no MCP dependency is required.
translate-agent-broker-old-to-new-project); standalone Mule apps, DataWeave, or APIs.If the YAML has schemaVersion: 1.0.0, this is V1 — stop and route to the converter. The V2 marker is agentNetwork: 2.0.0 (unquoted, top of file).
references/canonical-example.md — A complete, working Agent Network V2 (GA, A2A v1.0) project. The structural template — when in doubt, copy it.references/gotchas.md — GA syntax rules, compile-error rules, RULE-ASSET-MODE (inline vs Exchange), subagent-vs-orchestrator decision, auth casing, CLI + MCP tooling integration, graceful degradation.The MuleSoft Agent Network GA docs (Anypoint Code Builder section) are the authoritative reference. The references above cover the gotchas and worked example.
The 6 phases below use user-facing names for node types. The actual .agent file uses schema keywords. When talking to the user, use the phase name; when writing the file, use the keyword.
| Phase language | .agent keyword | What it is |
|---|---|---|
| Reasoning node | subagent | LLM-with-tools. Accepts actions; has built-in HITL. The default LLM-powered node type. |
| Orchestrator node | orchestrator | LLM-with-tools, specialized for coordinating multiple actions toward a compound goal. Use only when a node has ≥2 actions AND they jointly serve one outcome. |
| Generate node | generator | LLM without tools. For one-shot generation/summarization/classification with structured output. |
| (no LLM, deterministic) | router | Branching based on a known value. Conditions, not prompts. |
| (no LLM, side-effect) | executor | Runs one tool with known args, sets a variable. |
| (terminal) | echo | Sends the final A2A response to the client. |
The skill prefers the Anypoint CLI Agent Fabric plugin (mulesoft-anypoint-cli-agent-fabric-plugin) for validate/publish/deploy and Anypoint CLI v4 (anypoint-cli-v4) for Exchange search. The MuleSoft MCP server (mcp__mulesoft__*) is the fallback.
Try CLI first. If the CLI fails, fall back to MCP immediately — do NOT ask the user, do NOT retry the CLI, do NOT stop the phase.
A CLI attempt counts as failed when ANY of these happen:
command -v returns nothing (binary not installed).ENOENT, plugin not installed, auth env vars unset, network error, npm install needed, "command not found", EACCES).A CLI attempt does NOT count as failed when:
Fallback procedure (apply silently, in this order):
mcp__mulesoft__* tool is registered in the session. If yes, call it with the equivalent inputs.references/gotchas.md § "Graceful degradation".If a CLI command needs more info before running (unknown flag, unfamiliar subcommand, ambiguous syntax error): try <command> --help first, then a public-web search if --help doesn't resolve it. Only after both come up empty should you ask the user. This applies to the CLI plugin AND anypoint-cli-v4. Do NOT narrate the lookup; just run the command with the corrected syntax.
See references/gotchas.md § "Tooling integration" for the full capability matrix, CLI command syntax, env-var auth (ANYPOINT_CLIENT_ID/SECRET/ORG/ENV), and the per-step CLI ↔ MCP mapping.
The 6 phases below structure the build experience. Each phase ends with a stop point — wait for the user. Apply each user response immediately (no batch-then-update).
agent-network.yaml + exchange.json + brokers/, ask: "Edit this one, or scaffold new in a sibling folder?" Default edit (Workflow B).schemaVersion: 1.0.0 → route to converter.it-help-investigation) — also becomes the default assetId.0.0.0 while in development; user can bump on first publish).<project-name>/agent-network.yaml + exchange.json + brokers/ with the correct groupId/organizationId (pulled from ANYPOINT_ORG) and starter template. Skill then edits the generated files in place.
mcp__mulesoft__create_agent_network_project is present, call the MCP tool with the same inputs.agent-network.yaml with agentNetwork: 2.0.0, exchange.json with "classifier": "agentic-network", empty brokers/) and tell the user the groupId/organizationId placeholder needs to be filled in before publish.info for agent-network.yaml: ask for info.label (required) and info.description (optional). Default info.version to 1.0.0 unless user provides one. Apply to the scaffold immediately.Goal: Get the user to define functional requirements clearly. Refuse vague answers — keep prompting until each item is concrete. The user does not need to use graph terminology; natural-language steps are fine.
Capture, in order:
message/send. Confirm.)If the user gives a vague answer twice on the same item, accept a placeholder, flag it, and move on.
End the phase with one confirmation: "Here's what I captured: [bulleted summary]. Anything missing?" Stop.
Goal: Find the right assets in Exchange and register them in the YAML.
Asset types: LLMs (always ≥1), MCP tools, A2A agents.
Asset search order — for each capability identified in Phase 1:
anypoint-cli-v4 is installed: anypoint-cli-v4 exchange asset list --search "<keywords>" --organization <orgId>. Else if MCP search_asset is available: call with assetFilters: ["llm"] / ["mcp"] / ["agent"] + exchangeScope: "Private".--organization / set exchangeScope: "Public".${var}-style URL/auth placeholders the user can fill in later.LLM selection is different. Don't auto-pick. List the LLM options found in Exchange (e.g., claude, openai, gemini) and ask: "Pick one or more, or create a new one." Stop.
Review with the user before writing: "Selected: [list]. Confirm?" Stop.
Register every confirmed asset in agent-network.yaml + exchange.json. Each asset is in one of two modes — see references/gotchas.md § "RULE-ASSET-MODE":
context.connections with ref.name.exchange.json.dependencies + context.connections with ref.name AND ref.namespace. No registry entry.Auth always lives on context.connections.<id>.authentication. Parameterize URLs/secrets via ${<name>.url} / ${<name>.apiKey}. Add corresponding exchange.json.metadata.variables. Mark secrets "secret": true.
Per-type schema notes:
info.label, metadata.platform: Gemini | OpenAI | AzureOpenai. Connection: kind: llm + url + authentication.info.label, metadata.transport.kind (streamableHttp | sse | stdio). After registering, ask the user what tool_name to call (required for the action). Ask if they know the input parameters. If yes, declare in action inputs:. If no, omit inputs: — runtime auto-discovers. Never fabricate tool names or input schemas.info.label + interfaces branch. Use a2a for current A2A v1.0 agents, a2a_v03 for legacy A2A v0.3 (Agent Broker stays backward-compatible). Card under metadata.interfaces.<branch>.card includes name, description, url, protocolVersion, version, capabilities, defaultInputModes, defaultOutputModes, skills. See references/gotchas.md § "Registry agents" for the per-branch shape.Goal: Translate the functional requirements into the .agent graph. Brief drafts of system.instructions and per-node instructions only — Phase 5 refines prose.
Guiding principle: Graph = pre-defined rules. LLM node = reasoning. Use the graph for anything that can be definitively hard-coded. Use an LLM-powered node (reasoning/orchestrator/generate) only for tasks that genuinely need reasoning. The graph acts as the spine that enforces high-level stages (e.g. Research → Draft → Review); within each stage, the LLM-powered node has autonomy.
Write the first version of the graph:
agent_name from the user's requirements (kebab-case; also the .agent filename stem and broker id, e.g. it-help-investigation).kind: "a2a", target: "brokers://<broker-id>/a2a", on_message: is a fixed transition to. Conditionals in the trigger are a compile error — use a router downstream.subagent keyword) — LLM-with-tools. Default LLM-powered type. Has built-in HITL.orchestrator keyword) — LLM-with-tools, specialized for coordinating multiple actions toward a compound goal.generator keyword) — LLM-without-tools. One-shot generation, summarization, or classification with structured output.on_exit: -> transition to @<nodeType>.<nodeId>. Every reachable path terminates at echo.routes: + otherwise: and have no on_exit (transition to inside router on_exit is a compile error). Hard constraints from Phase 1 → router conditions, not prompts. Prompts can be ignored; router conditions cannot.@request.payload.message. Reference @request.payload.message.parts[0].text directly downstream.echo with kind: "a2a:status_update_event" (or "a2a:artifact_update_event" for artifacts). See references/gotchas.md § "Echo node" for the TASK_STATE_* enum and a2a.* helper rules.Write a first version of system.instructions and each LLM-powered node's prompt — keep them brief; Phase 5 refines.
Update the brokers entry in agent-network.yaml to reference the new .agent file. For full compile-error rules see references/gotchas.md § "Compile-error rules". For the structural template see references/canonical-example.md.
Goal: Assign assets from the YAML to the correct LLM-powered nodes.
Guiding principles:
subagent).orchestrator).executor nodes gated by router. Never put them on a reasoning/orchestrator node — the LLM could invoke them bypassing the router. Idempotent updates (status updates, ticket updates) MAY live on an orchestrator if part of the compound goal.Action:
.agent file. Each asset gets an actions: entry (A2A: target + kind only, no inputs:; MCP: target, kind, tool_name, optional inputs:). Reference from reasoning.actions (reasoning/orchestrator nodes) or do: run (executor nodes).For full binding rules see references/gotchas.md:
with message = in executor; MCP with rules; http_headers implicit.Goal: Refine and battle-test instructions on every LLM-powered node. One node at a time, never batch.
For each generate/reasoning/orchestrator node:
classifySeverity." (Don't repeat which node you're on across turns — the user remembers.)system.instructions (the brief draft from Phase 3).outputs.properties.severity.enum, the prompt must say "Set severity to high when X, low otherwise" using the enum literals exactly.After every node is refined: run the cross-node contradiction test — does any prompt step conflict with another node's prompt or the graph? Surface conflicts to the user and resolve.
Cleanup, then validate.
Cleanup:
{{...}} markers, unused exchange.json variables.registry assets (not referenced by context.connections, actions, or LLM blocks).context.connections entries..agent file.registry.llms: with no entries → drop the key).Validate. Run the build command (CLI preferred → MCP fallback → structural checklist below + install hint). Full command syntax in references/gotchas.md § "Step 7 — Validate / build".
Structural checklist:
echo?router has routes (≥1) and otherwise?subagent/orchestrator has reasoning.instructions AND ≥1 action OR HITL?actions:?${...} variable has matching exchange.json.metadata.variables entry?context.connections.<id>.ref.name resolves to a registry entry OR exchange.json.dependencies?reasoning.actions are bare references (no with message =)?with parameters reference declared inputs: fields?state values in the allowed enum?max_number_of_loops lowered from default 25 (e.g., 3 classification, 5–10 orchestration); task_timeout_secs set if calling slow downstream agents?Fix loop:
When clean: "Project is validated and ready. Want to publish to Exchange and deploy to runtime?"
Only if user wants to. Prereqs: authenticated CLI/MCP context; exchange.json has assetVersion and no empty default: "" for secret: true variables.
Run the publish command (CLI preferred → MCP fallback → doc link). Surface published asset URLs from the output. Full command syntax is in references/gotchas.md § "Step 8 — Publish".
Only if user wants to. Publish must have happened first.
Ask the user: environmentName, targetSpace (private space), and any deployment properties for env-specific secrets (e.g., --property openai.apiKey:STAGING_API_KEY).
One-time setup per private space: if the target space has no gateways yet, run the gateway setup command first.
Run the deploy command (CLI preferred → MCP fallback → doc link). Surface deployment URL/ID. Full command syntax, gateway defaults, and CI flags are in references/gotchas.md § "Step 9 — Deploy".
Universal edit principles:
agent-network.yaml registry/context (or exchange.json.dependencies) BEFORE being referenced from .agent.gotchas.md).registry.{agents,mcps,llms} + context.connections.<id> with auth + exchange.json.metadata.variables. Exchange: exchange.json.dependencies + context.connections.<id> with ref.name + ref.namespace.actions: entry in the .agent file.reasoning.actions (subagent/orchestrator) or do: run (executor).subagent. Multi-action → orchestrator. Update @<oldType>.<id> references downstream.system.instructions to explain how to use the new asset.Edit .agent. After any change, walk trigger → every echo and confirm:
when: references a real, reachable upstream output (not @request.payload directly).transition to in a router's on_exit (compile error).Run Step 7.
Edit .agent only. Apply Phase 5 contradiction tests. If user pastes a policy doc, transform into numbered routine — don't paste verbatim. Run Step 7.
Edit agent-network.yaml. The GA schema supports policies even though the build flow doesn't surface them.
A policy has two parts:
context.policies.<policyId>.context.connections.<connId>.policies.outbound or brokers.<brokerId>.interfaces.a2a.policies.{inbound,outbound}. Always reference by id.For Exchange-published policies: add to exchange.json.dependencies first, then bind. Run Step 7.*