Skip to main content

Prompts live in files, not in YAML

You declare a path to a Markdown file. The engine loads and renders it per request.
agents:
  orders_agent:
    prompts:
      system: "prompts/orders/system.md"
      user: "prompts/orders/user.md"

orchestrators:
  router:
    prompts:
      orchestrator: "prompts/router/orchestrator.md"
      system: "prompts/router/system.md"
FieldApplies toRequired
orchestratorOrchestrators onlyYes
systemOrchestrators and agentsNo
userOrchestrators and agentsNo

Variables

Prompt files can contain {{variable}} placeholders:
You are a support agent for Acme Store.
Today is {{current_date}}.
You are helping {{customer_name}}.

Your account tier: {{account_tier}}.
Variables are filled by resolvers — Python methods that run before the agent executes. The LLM never sees the variable names, only the rendered values. Declare which resolvers a node uses:
resolvers:
  current_date:
    scope: shared
  customer_name:
    scope: shared
  account_tier:
    scope: agent

agents:
  orders_agent:
    prompts:
      system: "prompts/orders/system.md"
    resolvers: [current_date, customer_name, account_tier]
The resolver implementation (scaffolded by generate):
class SharedResolver:
    def current_date(self, ctx) -> str:
        return datetime.now().strftime("%Y-%m-%d")

    def customer_name(self, ctx) -> str:
        return ctx.headers.get("X-Customer-Name", "Customer")

class Resolver(SharedResolver):
    def account_tier(self, ctx) -> str:
        return fetch_account_tier(ctx.headers.get("X-Customer-Id"))

When rendering happens

At startup — prompt file paths are validated. If a file doesn’t exist, the engine fails before serving requests. Per request — resolvers run, variables are substituted, the final prompt string is produced. Rendered prompts are never cached globally — each request gets a fresh render with its own resolved values. This means dynamic values like current_date, customer_name, or account_tier are always accurate per request, regardless of when the engine started.

Rules

  • A variable with no matching resolver fails clearly — the engine names the node, the variable, and what’s missing.
  • Prompt text is not a security boundary. Don’t rely on prompt instructions to enforce access control — use the access plugin and runtime hooks instead.
  • Secrets must never appear in prompt files or YAML.