Examples
Patterns for defining Experts. Each example highlights a specific skill type or integration approach.
- Hard Signal Verification
- GitHub Issue Bot
- Web Search
- Custom MCP Server
- Interactive Wizard
- Application Integration
Hard Signal Verification
Section titled “Hard Signal Verification”Pattern: Combine a soft review gate with hard signal verification in the delegation tree. The reviewer catches semantic issues early; the verifier provides the final deterministic pass/fail. See combining soft and hard signals for the full rationale.
# Delegation Tree## app-builder — coordinator: build → review → verify cycle# ├── @app-builder/build — writes code to workspace# ├── @app-builder/review — checks requirements alignment (soft gate)# └── @app-builder/verify — runs hard signal checks, reports PASS/CONTINUE
[experts."app-builder"]description = "Builds a web application with verified output"instruction = """Coordinate the build-review-verify cycle:1. Delegate to build with the user's requirements2. Delegate to review with the requirements and build output3. If review returns CONTINUE: delegate to build with review feedback, restart from 24. If review returns PASS: delegate to verify with the build result5. If verify returns CONTINUE: delegate to build with failure feedback, restart from 26. If verify returns PASS: done"""delegates = ["@app-builder/build", "@app-builder/review", "@app-builder/verify"]
[experts."app-builder".skills."@perstack/base"]type = "mcpStdioSkill"command = "npx"packageName = "@perstack/base"pick = ["readTextFile", "attemptCompletion"]
[experts."@app-builder/build"]description = "Writes application code to the workspace. Provide requirements or failure feedback to address."instruction = """Write working application code. Focus on correctness over style.If failure feedback is provided, fix the specific issues."""
[experts."@app-builder/build".skills."@perstack/base"]type = "mcpStdioSkill"command = "npx"packageName = "@perstack/base"pick = ["readTextFile", "writeTextFile", "editTextFile", "exec", "attemptCompletion"]
[experts."@app-builder/review"]description = """Reviews the build output against requirements for completeness and alignment.Provide: requirements and path to built code. Returns PASS or CONTINUE with specific gaps."""instruction = """Read the requirements and the generated code.Check whether each requirement is addressed. Flag omissions or misinterpretations.Do NOT evaluate code quality or run any checks — that is the verifier's job."""
[experts."@app-builder/review".skills."@perstack/base"]type = "mcpStdioSkill"command = "npx"packageName = "@perstack/base"pick = ["readTextFile", "attemptCompletion"]
[experts."@app-builder/verify"]description = """Runs hard signal checks against the build output.Provide: what was built and where. Returns PASS or CONTINUE with specific failures."""instruction = """You are a verifier. Run commands and compare outputs. Do NOT read code and form opinions.
Checks:- TypeScript compiles: `npx tsc --noEmit` → exit code 0- Tests pass: `npm test` → exit code 0- App starts: `timeout 5 node dist/index.js` → no crash within 5 seconds
Run each check twice. If results differ between runs, report CONTINUE — the signal is non-deterministic.
Report per check: command, expected, actual, PASS/FAIL."""
[experts."@app-builder/verify".skills."@perstack/base"]type = "mcpStdioSkill"command = "npx"packageName = "@perstack/base"pick = ["readTextFile", "exec", "attemptCompletion"]Key design decisions:
- Reviewer is read-only —
pickhas noexec. It reads files and judges semantic alignment. This is a soft signal — qualitative judgment that only an LLM can provide — but it catches requirement gaps before the expensive verify cycle. - Verifier has
exec— it runs commands and compares outputs. No LLM judgment involved. This is the hard signal that provides the final pass/fail. - Review before verify — soft gate catches semantic drift early. Hard gate catches runtime failures. Neither replaces the other.
- Verifier is a direct child of the coordinator — not nested under
build. This guarantees context separation. - Reproducibility check — each command runs twice. If results differ, the signal is non-deterministic and cannot be trusted.
For a production example of this pattern, see create-expert — Perstack’s built-in Expert for generating Expert definitions, which uses review-definition (soft gate for plan alignment) followed by test-expert → verify-test (hard signal checks with reproducibility verification).
GitHub Issue Bot
Section titled “GitHub Issue Bot”Pattern: Use requiredEnv to pass environment variables to tools like gh CLI.
[experts."@perstack/github-issue-bot"]description = "Answers GitHub issues by reading codebase"instruction = """You are a GitHub issue support bot.Use `gh` CLI to fetch issue content, explore the codebase, and generate answers."""
[experts."@perstack/github-issue-bot".skills."@perstack/base"]type = "mcpStdioSkill"command = "npx"packageName = "@perstack/base"requiredEnv = ["GH_TOKEN", "GITHUB_REPO", "ISSUE_NUMBER"]This Expert is published to the registry. Run it with:
npx perstack run @perstack/github-issue-bot "Answer issue #123"See examples/github-issue-bot for complete setup including GitHub Actions workflow and real-time activity logging.
Web Search
Section titled “Web Search”Pattern: Use mcpStdioSkill with an npm package. Auto-installed at runtime.
[experts."market-monitor"]description = "Monitors stock market changes and analyzes trends"instruction = """You are a market monitoring assistant.Search for latest market news, compare with previous reports, and highlight changes."""
[experts."market-monitor".skills."web-search"]type = "mcpStdioSkill"command = "npx"packageName = "exa-mcp-server"requiredEnv = ["EXA_API_KEY"]Uses Exa MCP Server. Set EXA_API_KEY environment variable.
Custom MCP Server
Section titled “Custom MCP Server”Pattern: Use mcpStdioSkill with your own MCP server for internal systems.
[experts."support-assistant"]description = "Provides customer support using internal knowledge base"instruction = """You are a customer support assistant.Look up customer info, search the knowledge base, and provide solutions."""
[experts."support-assistant".skills."customer-db"]type = "mcpStdioSkill"command = "node"args = ["./mcp-servers/customer-db.js"]requiredEnv = ["DB_CONNECTION_STRING"]
[experts."support-assistant".skills."knowledge-base"]type = "mcpStdioSkill"command = "node"args = ["./mcp-servers/knowledge-base.js"]Implement MCP servers in Node.js, Python, or any language. Keep credentials in environment variables.
Interactive Wizard
Section titled “Interactive Wizard”Pattern: Use interactiveSkill to pause execution and wait for user input.
[experts."project-setup"]description = "Guides users through project setup"instruction = """You are a setup wizard.Use askChoice to ask about project type, framework, and tooling.Generate config files based on selections."""
[experts."project-setup".skills."interaction"]type = "interactiveSkill"
[experts."project-setup".skills."interaction".tools."askChoice"]description = "Ask user to choose from options"inputJsonSchema = """{ "type": "object", "properties": { "question": { "type": "string" }, "options": { "type": "array", "items": { "type": "string" } } }, "required": ["question", "options"]}"""When askChoice is called, execution pauses until the user responds.
Application Integration
Section titled “Application Integration”Pattern: Use interactiveSkill to let your application handle operations the Expert triggers.
[experts."shopping-concierge"]description = "Helps find products and add to cart"instruction = """You are a shopping assistant.Find matching products, then use addToCart to add them."""
[experts."shopping-concierge".skills."catalog"]type = "mcpStdioSkill"command = "node"args = ["./mcp-servers/product-catalog.js"]
[experts."shopping-concierge".skills."app"]type = "interactiveSkill"
[experts."shopping-concierge".skills."app".tools."addToCart"]description = "Add product to cart"inputJsonSchema = """{ "type": "object", "properties": { "productId": { "type": "string" }, "quantity": { "type": "number" } }, "required": ["productId", "quantity"]}"""When addToCart is called, execution pauses and returns control to your application. Your app performs the cart operation, then resumes the Expert. This pattern separates AI reasoning from actual operations.