Add ez-assistant and kerberos service folders

This commit is contained in:
kelin
2026-02-11 14:56:03 -05:00
parent e4e8ae1b87
commit 9ccfb36923
4471 changed files with 746463 additions and 0 deletions

View File

@@ -0,0 +1,951 @@
---
role: antipatterns
summary: |
Common mistakes and patterns to avoid in OpenProse programs.
Read this file to identify and fix problematic code patterns.
see-also:
- prose.md: Execution semantics, how to run programs
- compiler.md: Full syntax grammar, validation rules
- patterns.md: Recommended design patterns
---
# OpenProse Antipatterns
This document catalogs patterns that lead to brittle, expensive, slow, or unmaintainable programs. Each antipattern includes recognition criteria and remediation guidance.
---
## Structural Antipatterns
#### god-session
A single session that tries to do everything. God sessions are hard to debug, impossible to parallelize, and produce inconsistent results.
```prose
# Bad: One session doing too much
session """
Read all the code in the repository.
Identify security vulnerabilities.
Find performance bottlenecks.
Check for style violations.
Generate a comprehensive report.
Suggest fixes for each issue.
Prioritize by severity.
Create a remediation plan.
"""
```
**Why it's bad**: The session has no clear completion criteria. It mixes concerns that could be parallelized. Failure anywhere fails everything.
**Fix**: Decompose into focused sessions:
```prose
# Good: Focused sessions
parallel:
security = session "Identify security vulnerabilities"
perf = session "Find performance bottlenecks"
style = session "Check for style violations"
session "Synthesize findings and prioritize by severity"
context: { security, perf, style }
session "Create remediation plan"
```
#### sequential-when-parallel
Running independent operations sequentially when they could run concurrently. Wastes wall-clock time.
```prose
# Bad: Sequential independent work
let market = session "Research market"
let tech = session "Research technology"
let competition = session "Research competition"
session "Synthesize"
context: [market, tech, competition]
```
**Why it's bad**: Total time is sum of all research times. Each session waits for the previous one unnecessarily.
**Fix**: Parallelize independent work:
```prose
# Good: Parallel independent work
parallel:
market = session "Research market"
tech = session "Research technology"
competition = session "Research competition"
session "Synthesize"
context: { market, tech, competition }
```
#### spaghetti-context
Context passed haphazardly without clear data flow. Makes programs hard to understand and modify.
```prose
# Bad: Unclear what context is actually used
let a = session "Step A"
let b = session "Step B"
context: a
let c = session "Step C"
context: [a, b]
let d = session "Step D"
context: [a, b, c]
let e = session "Step E"
context: [a, c, d] # Why not b?
let f = session "Step F"
context: [a, b, c, d, e] # Everything?
```
**Why it's bad**: Unclear which sessions depend on which outputs. Hard to parallelize or refactor.
**Fix**: Minimize context to actual dependencies:
```prose
# Good: Clear, minimal dependencies
let research = session "Research"
let analysis = session "Analyze"
context: research
let recommendations = session "Recommend"
context: analysis # Only needs analysis, not research
let report = session "Report"
context: recommendations
```
#### parallel-then-synthesize
Spawning parallel agents for related analytical work, then synthesizing, when a single focused agent could do the entire job more efficiently.
```prose
# Antipattern: Parallel investigation + synthesis
parallel:
code = session "Analyze code path"
logs = session "Analyze logs"
context = session "Analyze execution context"
synthesis = session "Synthesize all findings"
context: { code, logs, context }
# 4 LLM calls, coordination overhead, fragmented context
```
**Why it's bad**: For related analysis that feeds into one conclusion, the coordination overhead and context fragmentation often outweigh parallelism benefits. Each parallel agent sees only part of the picture.
**Fix**: Use a single focused agent with multi-step instructions:
```prose
# Good: Single comprehensive investigator
diagnosis = session "Investigate the error"
prompt: """Analyze comprehensively:
1. Check the code path that produced the error
2. Examine logs for timing and state
3. Review execution context
Synthesize into a unified diagnosis."""
# 1 LLM call, full context, no coordination
```
**When parallel IS right**: When analyses are truly independent (security vs performance), when you want diverse perspectives that shouldn't influence each other, or when the work is so large it genuinely benefits from division.
#### copy-paste-workflows
Duplicating session sequences instead of using blocks. Leads to inconsistent changes and maintenance burden.
```prose
# Bad: Duplicated workflow
session "Security review of module A"
session "Performance review of module A"
session "Synthesize reviews of module A"
session "Security review of module B"
session "Performance review of module B"
session "Synthesize reviews of module B"
session "Security review of module C"
session "Performance review of module C"
session "Synthesize reviews of module C"
```
**Why it's bad**: If the workflow needs to change, you must change it everywhere. Easy to miss one.
**Fix**: Extract into a block:
```prose
# Good: Reusable block
block review-module(module):
parallel:
sec = session "Security review of {module}"
perf = session "Performance review of {module}"
session "Synthesize reviews of {module}"
context: { sec, perf }
do review-module("module A")
do review-module("module B")
do review-module("module C")
```
---
## Robustness Antipatterns
#### unbounded-loop
A loop without max iterations. Can run forever if the condition is never satisfied.
```prose
# Bad: No escape hatch
loop until **the code is perfect**:
session "Improve the code"
```
**Why it's bad**: "Perfect" may never be achieved. The program could run indefinitely, consuming resources.
**Fix**: Always specify `max:`:
```prose
# Good: Bounded iteration
loop until **the code is perfect** (max: 10):
session "Improve the code"
```
#### optimistic-execution
Assuming everything will succeed. No error handling for operations that can fail.
```prose
# Bad: No error handling
session "Call external API"
session "Process API response"
session "Store results in database"
session "Send notification"
```
**Why it's bad**: If the API fails, subsequent sessions receive no valid input. Silent corruption.
**Fix**: Handle failures explicitly:
```prose
# Good: Error handling
try:
let response = session "Call external API"
retry: 3
backoff: "exponential"
session "Process API response"
context: response
catch as err:
session "Handle API failure gracefully"
context: err
```
#### ignored-errors
Using `on-fail: "ignore"` when failures actually matter. Masks problems that should surface.
```prose
# Bad: Ignoring failures that matter
parallel (on-fail: "ignore"):
session "Charge customer credit card"
session "Ship the product"
session "Send confirmation email"
session "Order complete!" # But was it really?
```
**Why it's bad**: The order might be marked complete even if payment failed.
**Fix**: Use appropriate failure policy:
```prose
# Good: Fail-fast for critical operations
parallel: # Default: fail-fast
payment = session "Charge customer credit card"
inventory = session "Reserve inventory"
# Only ship if both succeeded
session "Ship the product"
context: { payment, inventory }
# Email can fail without blocking
try:
session "Send confirmation email"
catch:
session "Queue email for retry"
```
#### vague-discretion
Discretion conditions that are ambiguous or unmeasurable.
```prose
# Bad: What does "good enough" mean?
loop until **the output is good enough**:
session "Improve output"
# Bad: Highly subjective
if **the user will be happy**:
session "Ship it"
```
**Why it's bad**: The VM has no clear criteria for evaluation. Results are unpredictable.
**Fix**: Provide concrete, evaluatable criteria:
```prose
# Good: Specific criteria
loop until **all tests pass and code coverage exceeds 80%** (max: 10):
session "Improve test coverage"
# Good: Observable conditions
if **the response contains valid JSON with all required fields**:
session "Process the response"
```
#### catch-and-swallow
Catching errors without meaningful handling. Hides problems without solving them.
```prose
# Bad: Silent swallow
try:
session "Critical operation"
catch:
# Nothing here - error disappears
```
**Why it's bad**: Errors vanish. No recovery, no logging, no visibility.
**Fix**: Handle errors meaningfully:
```prose
# Good: Meaningful handling
try:
session "Critical operation"
catch as err:
session "Log error for investigation"
context: err
session "Execute fallback procedure"
# Or rethrow if unrecoverable:
throw
```
---
## Cost Antipatterns
#### opus-for-everything
Using the most powerful (expensive) model for all tasks, including trivial ones.
```prose
# Bad: Opus for simple classification
agent classifier:
model: opus
prompt: "Categorize items as: spam, not-spam"
# Expensive for a binary classification
for email in emails:
session: classifier
prompt: "Classify: {email}"
```
**Why it's bad**: Opus costs significantly more than haiku. Simple tasks don't benefit from advanced reasoning.
**Fix**: Match model to task complexity:
```prose
# Good: Haiku for simple tasks
agent classifier:
model: haiku
prompt: "Categorize items as: spam, not-spam"
```
#### context-bloat
Passing excessive context that the session doesn't need.
```prose
# Bad: Passing everything
let full_codebase = session "Read entire codebase"
let all_docs = session "Read all documentation"
let history = session "Get full git history"
session "Fix the typo in the README"
context: [full_codebase, all_docs, history] # Massive overkill
```
**Why it's bad**: Large contexts slow processing, increase costs, and can confuse the model with irrelevant information.
**Fix**: Pass minimal relevant context:
```prose
# Good: Minimal context
let readme = session "Read the README file"
session "Fix the typo in the README"
context: readme
```
#### unnecessary-iteration
Looping when a single session would suffice.
```prose
# Bad: Loop for what could be one call
let items = ["apple", "banana", "cherry"]
for item in items:
session "Describe {item}"
```
**Why it's bad**: Three sessions when one could handle all items. Session overhead multiplied.
**Fix**: Batch when possible:
```prose
# Good: Batch processing
let items = ["apple", "banana", "cherry"]
session "Describe each of these items: {items}"
```
#### redundant-computation
Computing the same thing multiple times.
```prose
# Bad: Redundant research
session "Research AI safety for security review"
session "Research AI safety for ethics review"
session "Research AI safety for compliance review"
```
**Why it's bad**: Same research done three times with slightly different framing.
**Fix**: Compute once, use many times:
```prose
# Good: Compute once
let research = session "Comprehensive research on AI safety"
parallel:
session "Security review"
context: research
session "Ethics review"
context: research
session "Compliance review"
context: research
```
---
## Performance Antipatterns
#### eager-over-computation
Computing everything upfront when only some results might be needed.
```prose
# Bad: Compute all branches even if only one is needed
parallel:
simple_analysis = session "Simple analysis"
model: haiku
detailed_analysis = session "Detailed analysis"
model: sonnet
deep_analysis = session "Deep analysis"
model: opus
# Then only use one based on some criterion
choice **appropriate depth**:
option "Simple":
session "Use simple"
context: simple_analysis
option "Detailed":
session "Use detailed"
context: detailed_analysis
option "Deep":
session "Use deep"
context: deep_analysis
```
**Why it's bad**: All three analyses run even though only one is used.
**Fix**: Compute lazily:
```prose
# Good: Only compute what's needed
let initial = session "Initial assessment"
model: haiku
choice **appropriate depth based on initial assessment**:
option "Simple":
session "Simple analysis"
model: haiku
option "Detailed":
session "Detailed analysis"
model: sonnet
option "Deep":
session "Deep analysis"
model: opus
```
#### over-parallelization
Parallelizing so aggressively that overhead dominates or resources are exhausted.
```prose
# Bad: 100 parallel sessions
parallel for item in large_collection: # 100 items
session "Process {item}"
```
**Why it's bad**: May overwhelm the system. Coordination overhead can exceed parallelism benefits.
**Fix**: Batch or limit concurrency:
```prose
# Good: Process in batches
for batch in batches(large_collection, 10):
parallel for item in batch:
session "Process {item}"
```
#### premature-parallelization
Parallelizing tiny tasks where sequential would be simpler and fast enough.
```prose
# Bad: Parallel overkill for simple tasks
parallel:
a = session "Add 2 + 2"
b = session "Add 3 + 3"
c = session "Add 4 + 4"
```
**Why it's bad**: Coordination overhead exceeds task time. Sequential would be simpler and possibly faster.
**Fix**: Keep it simple:
```prose
# Good: Sequential for trivial tasks
session "Add 2+2, 3+3, and 4+4"
```
#### synchronous-fire-and-forget
Waiting for operations whose results you don't need.
```prose
# Bad: Waiting for logging
session "Do important work"
session "Log the result" # Don't need to wait for this
session "Continue with next important work"
```
**Why it's bad**: Main workflow blocked by non-critical operation.
**Fix**: Use appropriate patterns for fire-and-forget operations, or batch logging:
```prose
# Better: Batch non-critical work
session "Do important work"
session "Continue with next important work"
# ... more important work ...
# Log everything at the end or async
session "Log all operations"
```
---
## Maintainability Antipatterns
#### magic-strings
Hardcoded prompts repeated throughout the program.
```prose
# Bad: Same prompt in multiple places
session "You are a helpful assistant. Analyze this code for bugs."
# ... later ...
session "You are a helpful assistant. Analyze this code for bugs."
# ... even later ...
session "You are a helpful assistent. Analyze this code for bugs." # Typo!
```
**Why it's bad**: Inconsistency when updating. Typos go unnoticed.
**Fix**: Use agents:
```prose
# Good: Single source of truth
agent code-analyst:
model: sonnet
prompt: "You are a helpful assistant. Analyze code for bugs."
session: code-analyst
prompt: "Analyze the auth module"
session: code-analyst
prompt: "Analyze the payment module"
```
#### opaque-workflow
No structure or comments indicating what's happening.
```prose
# Bad: What is this doing?
let x = session "A"
let y = session "B"
context: x
parallel:
z = session "C"
context: y
w = session "D"
session "E"
context: [z, w]
```
**Why it's bad**: Impossible to understand, debug, or modify.
**Fix**: Use meaningful names and structure:
```prose
# Good: Clear intent
# Phase 1: Research
let research = session "Gather background information"
# Phase 2: Analysis
let analysis = session "Analyze research findings"
context: research
# Phase 3: Parallel evaluation
parallel:
technical_eval = session "Technical feasibility assessment"
context: analysis
business_eval = session "Business viability assessment"
context: analysis
# Phase 4: Synthesis
session "Create final recommendation"
context: { technical_eval, business_eval }
```
#### implicit-dependencies
Relying on conversation history rather than explicit context.
```prose
# Bad: Implicit state
session "Set the project name to Acme"
session "Set the deadline to Friday"
session "Now create a project plan" # Hopes previous info is remembered
```
**Why it's bad**: Relies on VM implementation details. Fragile across refactoring.
**Fix**: Explicit context:
```prose
# Good: Explicit state
let config = session "Define project: name=Acme, deadline=Friday"
session "Create a project plan"
context: config
```
#### mixed-concerns-agent
Agents with prompts that cover too many responsibilities.
```prose
# Bad: Jack of all trades
agent super-agent:
model: opus
prompt: """
You are an expert in:
- Security analysis
- Performance optimization
- Code review
- Documentation
- Testing
- DevOps
- Project management
- Customer communication
When asked, perform any of these tasks.
"""
```
**Why it's bad**: No focus means mediocre results across the board. Can't optimize model choice.
**Fix**: Specialized agents:
```prose
# Good: Focused expertise
agent security-expert:
model: sonnet
prompt: "You are a security analyst. Focus only on security concerns."
agent performance-expert:
model: sonnet
prompt: "You are a performance engineer. Focus only on optimization."
agent technical-writer:
model: haiku
prompt: "You write clear technical documentation."
```
---
## Logic Antipatterns
#### infinite-refinement
Loops that can never satisfy their exit condition.
```prose
# Bad: Perfection is impossible
loop until **the code has zero bugs**:
session "Find and fix bugs"
```
**Why it's bad**: Zero bugs is unachievable. Loop runs until max (if specified) or forever.
**Fix**: Use achievable conditions:
```prose
# Good: Achievable condition
loop until **all known bugs are fixed** (max: 20):
session "Find and fix the next bug"
# Or: Diminishing returns
loop until **no significant bugs found in last iteration** (max: 10):
session "Search for bugs"
```
#### assertion-as-action
Using conditions as actions—checking something without acting on the result.
```prose
# Bad: Check but don't use result
session "Check if the system is healthy"
session "Deploy to production" # Deploys regardless!
```
**Why it's bad**: The health check result isn't used. Deploy happens unconditionally.
**Fix**: Use conditional execution:
```prose
# Good: Act on the check
let health = session "Check if the system is healthy"
if **system is healthy**:
session "Deploy to production"
else:
session "Alert on-call and skip deployment"
context: health
```
#### false-parallelism
Putting sequential-dependent operations in a parallel block.
```prose
# Bad: These aren't independent!
parallel:
data = session "Fetch data"
processed = session "Process the data" # Needs data!
context: data
stored = session "Store processed data" # Needs processed!
context: processed
```
**Why it's bad**: Despite being in parallel, these must run sequentially due to dependencies.
**Fix**: Be honest about dependencies:
```prose
# Good: Sequential where needed
let data = session "Fetch data"
let processed = session "Process the data"
context: data
session "Store processed data"
context: processed
```
#### exception-as-flow-control
Using try/catch for expected conditions rather than exceptional errors.
```prose
# Bad: Exceptions for normal flow
try:
session "Find the optional config file"
catch:
session "Use default configuration"
```
**Why it's bad**: Missing config is expected, not exceptional. Obscures actual errors.
**Fix**: Use conditionals for expected cases:
```prose
# Good: Conditional for expected case
let config_exists = session "Check if config file exists"
if **config file exists**:
session "Load configuration from file"
else:
session "Use default configuration"
```
#### excessive-user-checkpoints
Prompting the user for decisions that have obvious or predictable answers.
```prose
# Antipattern: Asking the obvious
input "Blocking error detected. Investigate?" # Always yes
input "Diagnosis complete. Proceed to triage?" # Always yes
input "Tests pass. Deploy?" # Almost always yes
```
**Why it's bad**: Each checkpoint is a round-trip waiting for user input. If the answer is predictable 90% of the time, you're adding latency for no value.
**Fix**: Auto-proceed for obvious cases, only prompt when genuinely ambiguous:
```prose
# Good: Auto-proceed with escape hatches for edge cases
if observation.blocking_error:
# Auto-investigate (don't ask - of course we investigate errors)
let diagnosis = do investigate(...)
# Only ask if genuinely ambiguous
if diagnosis.confidence == "low":
input "Low confidence diagnosis. Proceed anyway?"
# Auto-deploy if tests pass (but log for audit)
if fix.tests_pass:
do deploy(...)
```
**When checkpoints ARE right**: Irreversible actions (production deployments to critical systems), expensive operations (long-running jobs), or genuine decision points where the user's preference isn't predictable.
#### fixed-observation-window
Waiting for a predetermined duration when the signal arrived early.
```prose
# Antipattern: Fixed window regardless of findings
loop 30 times (wait: 2s each): # Always 60 seconds
resume: observer
prompt: "Keep watching the stream"
# Runs all 30 iterations even if blocking error detected on iteration 1
```
**Why it's bad**: Wastes time when the answer is already known. If the observer detected a fatal error at +5 seconds, why wait another 55 seconds?
**Fix**: Use signal-driven exit conditions:
```prose
# Good: Exit on significant signal
loop until **blocking error OR completion** (max: 30):
resume: observer
prompt: "Watch the stream. Signal IMMEDIATELY on blocking errors."
# Exits as soon as something significant happens
```
Or use `early_exit` if your runtime supports it:
```prose
# Good: Explicit early exit
let observation = session: observer
prompt: "Monitor for errors. Signal immediately if found."
timeout: 120s
early_exit: **blocking_error detected**
```
---
## Security Antipatterns
#### unvalidated-input
Passing external input directly to sessions without validation.
```prose
# Bad: Direct injection
let user_input = external_source
session "Execute this command: {user_input}"
```
**Why it's bad**: User could inject malicious prompts or commands.
**Fix**: Validate and sanitize:
```prose
# Good: Validate first
let user_input = external_source
let validated = session "Validate this input is a safe search query"
context: user_input
if **input is valid and safe**:
session "Search for: {validated}"
else:
throw "Invalid input rejected"
```
#### overprivileged-agents
Agents with more permissions than they need.
```prose
# Bad: Full access for simple task
agent file-reader:
permissions:
read: ["**/*"]
write: ["**/*"]
bash: allow
network: allow
session: file-reader
prompt: "Read the README.md file"
```
**Why it's bad**: Task only needs to read one file but has full system access.
**Fix**: Least privilege:
```prose
# Good: Minimal permissions
agent file-reader:
permissions:
read: ["README.md"]
write: []
bash: deny
network: deny
```
---
## Summary
Antipatterns emerge from:
1. **Laziness**: Copy-paste instead of abstraction, implicit instead of explicit
2. **Over-engineering**: Parallelizing everything, using opus for all tasks
3. **Under-engineering**: No error handling, unbounded loops, vague conditions
4. **Unclear thinking**: God sessions, mixed concerns, spaghetti context
When reviewing OpenProse programs, ask:
- Can independent work be parallelized?
- Are loops bounded?
- Are errors handled?
- Is context minimal and explicit?
- Are models matched to task complexity?
- Are agents focused and reusable?
- Would a stranger understand this code?
Fix antipatterns early. They compound over time into unmaintainable systems.

View File

@@ -0,0 +1,700 @@
---
role: best-practices
summary: |
Design patterns for robust, efficient, and maintainable OpenProse programs.
Read this file when authoring new programs or reviewing existing ones.
see-also:
- prose.md: Execution semantics, how to run programs
- compiler.md: Full syntax grammar, validation rules
- antipatterns.md: Patterns to avoid
---
# OpenProse Design Patterns
This document catalogs proven patterns for orchestrating AI agents effectively. Each pattern addresses specific concerns: robustness, cost efficiency, speed, maintainability, or self-improvement capability.
---
## Structural Patterns
#### parallel-independent-work
When tasks have no data dependencies, execute them concurrently. This maximizes throughput and minimizes wall-clock time.
```prose
# Good: Independent research runs in parallel
parallel:
market = session "Research market trends"
tech = session "Research technology landscape"
competition = session "Analyze competitor products"
session "Synthesize findings"
context: { market, tech, competition }
```
The synthesis session waits for all branches, but total time equals the longest branch rather than the sum of all branches.
#### fan-out-fan-in
For processing collections, fan out to parallel workers then collect results. Use `parallel for` instead of manual parallel branches.
```prose
let topics = ["AI safety", "interpretability", "alignment", "robustness"]
parallel for topic in topics:
session "Deep dive research on {topic}"
session "Create unified report from all research"
```
This scales naturally with collection size and keeps code DRY.
#### pipeline-composition
Chain transformations using pipe operators for readable data flow. Each stage has a single responsibility.
```prose
let candidates = session "Generate 10 startup ideas"
let result = candidates
| filter:
session "Is this idea technically feasible? yes/no"
context: item
| map:
session "Expand this idea into a one-page pitch"
context: item
| reduce(best, current):
session "Compare these two pitches, return the stronger one"
context: [best, current]
```
#### agent-specialization
Define agents with focused expertise. Specialized agents produce better results than generalist prompts.
```prose
agent security-reviewer:
model: sonnet
prompt: """
You are a security expert. Focus exclusively on:
- Authentication and authorization flaws
- Injection vulnerabilities
- Data exposure risks
Ignore style, performance, and other concerns.
"""
agent performance-reviewer:
model: sonnet
prompt: """
You are a performance engineer. Focus exclusively on:
- Algorithmic complexity
- Memory usage patterns
- I/O bottlenecks
Ignore security, style, and other concerns.
"""
```
#### reusable-blocks
Extract repeated workflows into parameterized blocks. Blocks are the functions of OpenProse.
```prose
block review-and-revise(artifact, criteria):
let feedback = session "Review {artifact} against {criteria}"
session "Revise {artifact} based on feedback"
context: feedback
# Reuse the pattern
do review-and-revise("the architecture doc", "clarity and completeness")
do review-and-revise("the API design", "consistency and usability")
do review-and-revise("the test plan", "coverage and edge cases")
```
---
## Robustness Patterns
#### bounded-iteration
Always constrain loops with `max:` to prevent runaway execution. Even well-crafted conditions can fail to terminate.
```prose
# Good: Explicit upper bound
loop until **all tests pass** (max: 20):
session "Identify and fix the next failing test"
# The program will terminate even if tests never fully pass
```
#### graceful-degradation
Use `on-fail: "continue"` when partial results are acceptable. Collect what you can rather than failing entirely.
```prose
parallel (on-fail: "continue"):
primary = session "Query primary data source"
backup = session "Query backup data source"
cache = session "Check local cache"
# Continue with whatever succeeded
session "Merge available data"
context: { primary, backup, cache }
```
#### retry-with-backoff
External services fail transiently. Retry with exponential backoff to handle rate limits and temporary outages.
```prose
session "Call external API"
retry: 5
backoff: "exponential"
```
For critical paths, combine retry with fallback:
```prose
try:
session "Call primary API"
retry: 3
backoff: "exponential"
catch:
session "Use fallback data source"
```
#### error-context-capture
Capture error context for intelligent recovery. The error variable provides information for diagnostic or remediation sessions.
```prose
try:
session "Deploy to production"
catch as err:
session "Analyze deployment failure and suggest fixes"
context: err
session "Attempt automatic remediation"
context: err
```
#### defensive-context
Validate assumptions before expensive operations. Cheap checks prevent wasted computation.
```prose
let prereqs = session "Check all prerequisites: API keys, permissions, dependencies"
if **prerequisites are not met**:
session "Report missing prerequisites and exit"
context: prereqs
throw "Prerequisites not satisfied"
# Expensive operations only run if prereqs pass
session "Execute main workflow"
```
---
## Cost Efficiency Patterns
#### model-tiering
Match model capability to task complexity:
| Model | Best For | Examples |
|-------|----------|----------|
| **Sonnet 4.5** | Orchestration, control flow, coordination | VM execution, captain's chair, workflow routing |
| **Opus 4.5** | Hard/difficult work requiring deep reasoning | Complex analysis, strategic decisions, novel problem-solving |
| **Haiku** | Simple, self-evident tasks (use sparingly) | Classification, summarization, formatting |
**Key insight:** Sonnet 4.5 excels at *orchestrating* agents and managing control flow—it's the ideal model for the OpenProse VM itself and for "captain" agents that coordinate work. Opus 4.5 should be reserved for agents doing genuinely difficult intellectual work. Haiku can handle simple tasks but should generally be avoided where quality matters.
**Detailed task-to-model mapping:**
| Task Type | Model | Rationale |
|-----------|-------|-----------|
| Orchestration, routing, coordination | Sonnet | Fast, good at following structure |
| Investigation, debugging, diagnosis | Sonnet | Structured analysis, checklist-style work |
| Triage, classification, categorization | Sonnet | Clear criteria, deterministic decisions |
| Code review, verification (checklist) | Sonnet | Following defined review criteria |
| Simple implementation, fixes | Sonnet | Applying known patterns |
| Complex multi-file synthesis | Opus | Needs to hold many things in context |
| Novel architecture, strategic planning | Opus | Requires creative problem-solving |
| Ambiguous problems, unclear requirements | Opus | Needs to reason through uncertainty |
**Rule of thumb:** If you can write a checklist for the task, Sonnet can do it. If the task requires genuine creativity or navigating ambiguity, use Opus.
```prose
agent captain:
model: sonnet # Orchestration and coordination
persist: true # Execution-scoped (dies with run)
prompt: "You coordinate the team and review work"
agent researcher:
model: opus # Hard analytical work
prompt: "You perform deep research and analysis"
agent formatter:
model: haiku # Simple transformation (use sparingly)
prompt: "You format text into consistent structure"
agent preferences:
model: sonnet
persist: user # User-scoped (survives across projects)
prompt: "You remember user preferences and patterns"
# Captain orchestrates, specialists do the hard work
session: captain
prompt: "Plan the research approach"
let findings = session: researcher
prompt: "Investigate the technical architecture"
resume: captain
prompt: "Review findings and determine next steps"
context: findings
```
#### context-minimization
Pass only relevant context. Large contexts slow processing and increase costs.
```prose
# Bad: Passing everything
session "Write executive summary"
context: [raw_data, analysis, methodology, appendices, references]
# Good: Pass only what's needed
let key_findings = session "Extract key findings from analysis"
context: analysis
session "Write executive summary"
context: key_findings
```
#### early-termination
Exit loops as soon as the goal is achieved. Don't iterate unnecessarily.
```prose
# The condition is checked each iteration
loop until **solution found and verified** (max: 10):
session "Generate potential solution"
session "Verify solution correctness"
# Exits immediately when condition is met, not after max iterations
```
#### early-signal-exit
When observing or monitoring, exit as soon as you have a definitive answer—don't wait for the full observation window.
```prose
# Good: Exit on signal
let observation = session: observer
prompt: "Watch the stream. Signal immediately if you detect a blocking error."
timeout: 120s
early_exit: **blocking_error detected**
# Bad: Fixed observation window
loop 30 times:
resume: observer
prompt: "Keep watching..." # Even if error was obvious at iteration 2
```
This respects signals when they arrive rather than waiting for arbitrary timeouts.
#### defaults-over-prompts
For standard configuration, use constants or environment variables. Only prompt when genuinely variable.
```prose
# Good: Sensible defaults
const API_URL = "https://api.example.com"
const TEST_PROGRAM = "# Simple test\nsession 'Hello'"
# Slower: Prompting for known values
let api_url = input "Enter API URL" # Usually the same value
let program = input "Enter test program" # Usually the same value
```
If 90% of runs use the same value, hardcode it. Let users override via CLI args if needed.
#### race-for-speed
When any valid result suffices, race multiple approaches and take the first success.
```prose
parallel ("first"):
session "Try algorithm A"
session "Try algorithm B"
session "Try algorithm C"
# Continues as soon as any approach completes
session "Use winning result"
```
#### batch-similar-work
Group similar operations to amortize overhead. One session with structured output beats many small sessions.
```prose
# Inefficient: Many small sessions
for file in files:
session "Analyze {file}"
# Efficient: Batch analysis
session "Analyze all files and return structured findings for each"
context: files
```
---
## Self-Improvement Patterns
#### self-verification-in-prompt
For tasks that would otherwise require a separate verifier, include verification as the final step in the prompt. This saves a round-trip while maintaining rigor.
```prose
# Good: Combined work + self-verification
agent investigator:
model: sonnet
prompt: """Diagnose the error.
1. Examine code paths
2. Check logs and state
3. Form hypothesis
4. BEFORE OUTPUTTING: Verify your evidence supports your conclusion.
Output only if confident. If uncertain, state what's missing."""
# Slower: Separate verifier agent
let diagnosis = session: researcher
prompt: "Investigate the error"
let verification = session: verifier
prompt: "Verify this diagnosis" # Extra round-trip
context: diagnosis
```
Use a separate verifier when you need genuine adversarial review (different perspective), but for self-consistency checks, bake verification into the prompt.
#### iterative-refinement
Use feedback loops to progressively improve outputs. Each iteration builds on the previous.
```prose
let draft = session "Create initial draft"
loop until **draft meets quality bar** (max: 5):
let critique = session "Critically evaluate this draft"
context: draft
draft = session "Improve draft based on critique"
context: [draft, critique]
session "Finalize and publish"
context: draft
```
#### multi-perspective-review
Gather diverse viewpoints before synthesis. Different lenses catch different issues.
```prose
parallel:
user_perspective = session "Evaluate from end-user viewpoint"
tech_perspective = session "Evaluate from engineering viewpoint"
business_perspective = session "Evaluate from business viewpoint"
session "Synthesize feedback and prioritize improvements"
context: { user_perspective, tech_perspective, business_perspective }
```
#### adversarial-validation
Use one agent to challenge another's work. Adversarial pressure improves robustness.
```prose
let proposal = session "Generate proposal"
let critique = session "Find flaws and weaknesses in this proposal"
context: proposal
let defense = session "Address each critique with evidence or revisions"
context: [proposal, critique]
session "Produce final proposal incorporating valid critiques"
context: [proposal, critique, defense]
```
#### consensus-building
For critical decisions, require agreement between independent evaluators.
```prose
parallel:
eval1 = session "Independently evaluate the solution"
eval2 = session "Independently evaluate the solution"
eval3 = session "Independently evaluate the solution"
loop until **evaluators agree** (max: 3):
session "Identify points of disagreement"
context: { eval1, eval2, eval3 }
parallel:
eval1 = session "Reconsider position given other perspectives"
context: { eval1, eval2, eval3 }
eval2 = session "Reconsider position given other perspectives"
context: { eval1, eval2, eval3 }
eval3 = session "Reconsider position given other perspectives"
context: { eval1, eval2, eval3 }
session "Document consensus decision"
context: { eval1, eval2, eval3 }
```
---
## Maintainability Patterns
#### descriptive-agent-names
Name agents for their role, not their implementation. Names should convey purpose.
```prose
# Good: Role-based naming
agent code-reviewer:
agent technical-writer:
agent data-analyst:
# Bad: Implementation-based naming
agent opus-agent:
agent session-1-handler:
agent helper:
```
#### prompt-as-contract
Write prompts that specify expected inputs and outputs. Clear contracts prevent misunderstandings.
```prose
agent json-extractor:
model: haiku
prompt: """
Extract structured data from text.
Input: Unstructured text containing entity information
Output: JSON object with fields: name, date, amount, status
If a field cannot be determined, use null.
Never invent information not present in the input.
"""
```
#### separation-of-concerns
Each session should do one thing well. Combine simple sessions rather than creating complex ones.
```prose
# Good: Single responsibility per session
let data = session "Fetch and validate input data"
let analysis = session "Analyze data for patterns"
context: data
let recommendations = session "Generate recommendations from analysis"
context: analysis
session "Format recommendations as report"
context: recommendations
# Bad: God session
session "Fetch data, analyze it, generate recommendations, and format a report"
```
#### explicit-context-flow
Make data flow visible through explicit context passing. Avoid relying on implicit conversation history.
```prose
# Good: Explicit flow
let step1 = session "First step"
let step2 = session "Second step"
context: step1
let step3 = session "Third step"
context: [step1, step2]
# Bad: Implicit flow (relies on conversation state)
session "First step"
session "Second step using previous results"
session "Third step using all previous"
```
---
## Performance Patterns
#### lazy-evaluation
Defer expensive operations until their results are needed. Don't compute what might not be used.
```prose
session "Assess situation"
if **detailed analysis needed**:
# Expensive operations only when necessary
parallel:
deep_analysis = session "Perform deep analysis"
model: opus
historical = session "Gather historical comparisons"
session "Comprehensive report"
context: { deep_analysis, historical }
else:
session "Quick summary"
model: haiku
```
#### progressive-disclosure
Start with fast, cheap operations. Escalate to expensive ones only when needed.
```prose
# Tier 1: Fast screening (haiku)
let initial = session "Quick assessment"
model: haiku
if **needs deeper review**:
# Tier 2: Moderate analysis (sonnet)
let detailed = session "Detailed analysis"
model: sonnet
context: initial
if **needs expert review**:
# Tier 3: Deep reasoning (opus)
session "Expert-level analysis"
model: opus
context: [initial, detailed]
```
#### work-stealing
Use `parallel ("any", count: N)` to get results as fast as possible from a pool of workers.
```prose
# Get 3 good ideas as fast as possible from 5 parallel attempts
parallel ("any", count: 3, on-fail: "ignore"):
session "Generate creative solution approach 1"
session "Generate creative solution approach 2"
session "Generate creative solution approach 3"
session "Generate creative solution approach 4"
session "Generate creative solution approach 5"
session "Select best from the first 3 completed"
```
---
## Composition Patterns
#### workflow-template
Create blocks that encode entire workflow patterns. Instantiate with different parameters.
```prose
block research-report(topic, depth):
let research = session "Research {topic} at {depth} level"
let analysis = session "Analyze findings about {topic}"
context: research
let report = session "Write {depth}-level report on {topic}"
context: [research, analysis]
# Instantiate for different needs
do research-report("market trends", "executive")
do research-report("technical architecture", "detailed")
do research-report("competitive landscape", "comprehensive")
```
#### middleware-pattern
Wrap sessions with cross-cutting concerns like logging, timing, or validation.
```prose
block with-validation(task, validator):
let result = session "{task}"
let valid = session "{validator}"
context: result
if **validation failed**:
throw "Validation failed for: {task}"
do with-validation("Generate SQL query", "Check SQL for injection vulnerabilities")
do with-validation("Generate config file", "Validate config syntax")
```
#### circuit-breaker
After repeated failures, stop trying and fail fast. Prevents cascading failures.
```prose
let failures = 0
let max_failures = 3
loop while **service needed and failures < max_failures** (max: 10):
try:
session "Call external service"
# Reset on success
failures = 0
catch:
failures = failures + 1
if **failures >= max_failures**:
session "Circuit open - using fallback"
throw "Service unavailable"
```
---
## Observability Patterns
#### checkpoint-narration
For long workflows, emit progress markers. Helps with debugging and monitoring.
```prose
session "Phase 1: Data Collection"
# ... collection work ...
session "Phase 2: Analysis"
# ... analysis work ...
session "Phase 3: Report Generation"
# ... report work ...
session "Phase 4: Quality Assurance"
# ... QA work ...
```
#### structured-output-contracts
Request structured outputs that can be reliably parsed and validated.
```prose
agent structured-reviewer:
model: sonnet
prompt: """
Always respond with this exact JSON structure:
{
"verdict": "pass" | "fail" | "needs_review",
"issues": [{"severity": "high"|"medium"|"low", "description": "..."}],
"suggestions": ["..."]
}
"""
let review = session: structured-reviewer
prompt: "Review this code for security issues"
```
---
## Summary
The most effective OpenProse programs combine these patterns:
1. **Structure**: Parallelize independent work, use blocks for reuse
2. **Robustness**: Bound loops, handle errors, retry transient failures
3. **Efficiency**: Tier models, minimize context, terminate early
4. **Quality**: Iterate, get multiple perspectives, validate adversarially
5. **Maintainability**: Name clearly, separate concerns, make flow explicit
Choose patterns based on your specific constraints. A quick prototype prioritizes speed over robustness. A production workflow prioritizes reliability over cost. A research exploration prioritizes thoroughness over efficiency.

View File

@@ -0,0 +1,180 @@
---
role: system-prompt-enforcement
summary: |
Strict system prompt addition for OpenProse VM instances. This enforces
that the agent ONLY executes .prose programs and embodies the VM correctly.
Append this to system prompts for dedicated OpenProse execution instances.
---
# OpenProse VM System Prompt Enforcement
**⚠️ CRITICAL: THIS INSTANCE IS DEDICATED TO OPENPROSE EXECUTION ONLY ⚠️**
This agent instance is configured exclusively for executing OpenProse (`.prose`) programs. You MUST NOT execute, interpret, or respond to any non-Prose tasks. If a user requests anything other than a `prose` command or `.prose` program execution, you MUST refuse and redirect them to use a general-purpose agent.
## Your Role: You ARE the OpenProse VM
You are not simulating a virtual machine—you **ARE** the OpenProse VM. When executing a `.prose` program:
- **Your conversation history** = The VM's working memory
- **Your Task tool calls** = The VM's instruction execution
- **Your state tracking** = The VM's execution trace
- **Your judgment on `**...**`** = The VM's intelligent evaluation
### Core Execution Principles
1. **Strict Structure**: Follow the program structure exactly as written
2. **Intelligent Evaluation**: Use judgment only for discretion conditions (`**...**`)
3. **Real Execution**: Each `session` spawns a real subagent via Task tool
4. **State Persistence**: Track state in `.prose/runs/{id}/` or via narration protocol
## Execution Model
### Sessions = Function Calls
Every `session` statement triggers a Task tool call:
```prose
session "Research quantum computing"
```
Execute as:
```
Task({
description: "OpenProse session",
prompt: "Research quantum computing",
subagent_type: "general-purpose"
})
```
### Context Passing (By Reference)
The VM passes context **by reference**, never by value:
```
Context (by reference):
- research: .prose/runs/{id}/bindings/research.md
Read this file to access the content. The VM never holds full binding values.
```
### Parallel Execution
`parallel:` blocks spawn multiple sessions concurrently—call all Task tools in a single response:
```prose
parallel:
a = session "Task A"
b = session "Task B"
```
Execute by calling both Task tools simultaneously, then wait for all to complete.
### Persistent Agents
- `session: agent` = Fresh start (ignores memory)
- `resume: agent` = Load memory, continue with context
For `resume:`, include the agent's memory file path and instruct the subagent to read/update it.
### Control Flow
- **Loops**: Evaluate condition, execute body, repeat until condition met or max reached
- **Try/Catch**: Execute try, catch on error, always execute finally
- **Choice/If**: Evaluate conditions, execute first matching branch only
- **Blocks**: Push frame, bind arguments, execute body, pop frame
## State Management
Default: File-system state in `.prose/runs/{id}/`
- `state.md` = VM execution state (written by VM only)
- `bindings/{name}.md` = Variable values (written by subagents)
- `agents/{name}/memory.md` = Persistent agent memory
Subagents write their outputs directly to binding files and return confirmation messages (not full content) to the VM.
## File Location Index
**Do NOT search for OpenProse documentation files.** All skill files are installed in the skills directory. Use the following paths (with placeholder `{OPENPROSE_SKILL_DIR}` that will be replaced with the actual skills directory path):
| File | Location | Purpose |
| ----------------------- | --------------------------------------------- | ---------------------------------------------- |
| `prose.md` | `{OPENPROSE_SKILL_DIR}/prose.md` | VM semantics (load to run programs) |
| `state/filesystem.md` | `{OPENPROSE_SKILL_DIR}/state/filesystem.md` | File-based state (default, load with VM) |
| `state/in-context.md` | `{OPENPROSE_SKILL_DIR}/state/in-context.md` | In-context state (on request) |
| `state/sqlite.md` | `{OPENPROSE_SKILL_DIR}/state/sqlite.md` | SQLite state (experimental, on request) |
| `state/postgres.md` | `{OPENPROSE_SKILL_DIR}/state/postgres.md` | PostgreSQL state (experimental, on request) |
| `primitives/session.md` | `{OPENPROSE_SKILL_DIR}/primitives/session.md` | Session context and compaction guidelines |
| `compiler.md` | `{OPENPROSE_SKILL_DIR}/compiler.md` | Compiler/validator (load only on request) |
| `help.md` | `{OPENPROSE_SKILL_DIR}/help.md` | Help, FAQs, onboarding (load for `prose help`) |
**When to load these files:**
- **Always load `prose.md`** when executing a `.prose` program
- **Load `state/filesystem.md`** with `prose.md` (default state mode)
- **Load `state/in-context.md`** only if user requests `--in-context` or says "use in-context state"
- **Load `state/sqlite.md`** only if user requests `--state=sqlite` (requires sqlite3 CLI)
- **Load `state/postgres.md`** only if user requests `--state=postgres` (requires psql + PostgreSQL)
- **Load `primitives/session.md`** when working with persistent agents (`resume:`)
- **Load `compiler.md`** only when user explicitly requests compilation or validation
- **Load `help.md`** only for `prose help` command
Never search the user's workspace for these files—they are installed in the skills directory.
## Critical Rules
### ⛔ DO NOT:
- Execute any non-Prose code or scripts
- Respond to general programming questions
- Perform tasks outside `.prose` program execution
- Skip program structure or modify execution flow
- Hold full binding values in VM context (use references only)
### ✅ DO:
- Execute `.prose` programs strictly according to structure
- Spawn sessions via Task tool for every `session` statement
- Track state in `.prose/runs/{id}/` directory
- Pass context by reference (file paths, not content)
- Evaluate discretion conditions (`**...**`) intelligently
- Refuse non-Prose requests and redirect to general-purpose agent
## When User Requests Non-Prose Tasks
**Standard Response:**
```
⚠️ This agent instance is dedicated exclusively to executing OpenProse programs.
I can only execute:
- `prose run <file.prose>`
- `prose compile <file>`
- `prose help`
- `prose examples`
- Other `prose` commands
For general programming tasks, please use a general-purpose agent instance.
```
## Execution Algorithm (Simplified)
1. Parse program structure (use statements, inputs, agents, blocks)
2. Bind inputs from caller or prompt user if missing
3. For each statement in order:
- `session` → Task tool call, await result
- `resume` → Load memory, Task tool call, await result
- `let/const` → Execute RHS, bind result
- `parallel` → Spawn all branches concurrently, await per strategy
- `loop` → Evaluate condition, execute body, repeat
- `try/catch` → Execute try, catch on error, always finally
- `choice/if` → Evaluate conditions, execute matching branch
- `do block` → Push frame, bind args, execute body, pop frame
4. Collect output bindings
5. Return outputs to caller
## Remember
**You are the VM. The program is the instruction set. Execute it precisely, intelligently, and exclusively.**