Class: Mistri::Definition
- Inherits:
-
Object
- Object
- Mistri::Definition
- Defined in:
- lib/mistri/definition.rb
Overview
An agent definition: a markdown file whose YAML frontmatter carries the config and whose body is the prompt. Prompts stay editable prose in files a reviewer can diff; code stays out of them.
---
role: Trip Planner
model: claude-opus-4-8
tools:
- search_flights
- book_hotel
---
You plan trips end to end. Address the traveler as {first_name}.
definition = Mistri::Definition.load("app/agents/trip_planner.md")
agent = Mistri.agent(definition.model,
system: definition.render(first_name: traveler.first_name),
tools: registry.build(definition.tools, traveler))
The gem reads the file; what tool names mean, and what any extra frontmatter keys mean, stays the host's vocabulary via #config.
Constant Summary collapse
- FRONTMATTER =
/\A---\s*\n(?<yaml>.*?)\n---\s*\n(?<body>.*)\z/m
Instance Attribute Summary collapse
-
#body ⇒ Object
readonly
Returns the value of attribute body.
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(name:, config:, body:) ⇒ Definition
constructor
A new instance of Definition.
- #model ⇒ Object
-
#render(vars = {}) ⇒ Object
The body with placeholders filled in.
- #role ⇒ Object
- #tool_names ⇒ Object
-
#tools ⇒ Object
Tool declarations as a name => options map.
Constructor Details
#initialize(name:, config:, body:) ⇒ Definition
Returns a new instance of Definition.
41 42 43 44 45 46 |
# File 'lib/mistri/definition.rb', line 41 def initialize(name:, config:, body:) @name = name.to_s @config = config.freeze @body = body freeze end |
Instance Attribute Details
#body ⇒ Object (readonly)
Returns the value of attribute body.
29 30 31 |
# File 'lib/mistri/definition.rb', line 29 def body @body end |
#config ⇒ Object (readonly)
Returns the value of attribute config.
29 30 31 |
# File 'lib/mistri/definition.rb', line 29 def config @config end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
29 30 31 |
# File 'lib/mistri/definition.rb', line 29 def name @name end |
Class Method Details
.load(path) ⇒ Object
31 32 33 34 35 36 37 38 39 |
# File 'lib/mistri/definition.rb', line 31 def self.load(path) match = FRONTMATTER.match(File.read(path)) raise ConfigurationError, "#{path} has no frontmatter" unless match config = YAML.safe_load(match[:yaml]) || {} raise ConfigurationError, "#{path} frontmatter is not a mapping" unless config.is_a?(Hash) new(name: File.basename(path.to_s, ".md"), config: config, body: match[:body].strip) end |
Instance Method Details
#model ⇒ Object
48 |
# File 'lib/mistri/definition.rb', line 48 def model = config["model"] |
#render(vars = {}) ⇒ Object
The body with placeholders filled in. An unfilled placeholder raises: a prompt silently addressing "first_name" is worse than an error. A value of nil renders as empty, which lets optional context collapse cleanly.
71 72 73 74 75 76 77 78 |
# File 'lib/mistri/definition.rb', line 71 def render(vars = {}) vars = vars.transform_keys(&:to_s) body.gsub(/\{(\w+)\}/) do vars.fetch(Regexp.last_match(1)) do |key| raise ConfigurationError, "no value for {#{key}} in the #{name} definition" end end end |
#role ⇒ Object
50 |
# File 'lib/mistri/definition.rb', line 50 def role = config["role"] |
#tool_names ⇒ Object
65 |
# File 'lib/mistri/definition.rb', line 65 def tool_names = tools.keys |
#tools ⇒ Object
Tool declarations as a name => options map. A bare list means no options; a map form carries per-tool options in the host's vocabulary (gates, caching, whatever the host honors).
55 56 57 58 59 60 61 62 63 |
# File 'lib/mistri/definition.rb', line 55 def tools raw = config["tools"] entries = case raw when Hash then raw.transform_values { || || {} } when Array then raw.to_h { |tool| [tool, {}] } else {} end entries.transform_keys(&:to_s) end |