Skip to content
Home
GitHub

Examples

Patterns for defining Experts. Each example highlights a specific skill type or integration approach.

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 requirements
2. Delegate to review with the requirements and build output
3. If review returns CONTINUE: delegate to build with review feedback, restart from 2
4. If review returns PASS: delegate to verify with the build result
5. If verify returns CONTINUE: delegate to build with failure feedback, restart from 2
6. 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-onlypick has no exec. 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-expertverify-test (hard signal checks with reproducibility verification).

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:

Terminal window
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.

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.

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.

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.

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.