little_ghost 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +20 -10
  3. data/docs/guides/assemblies.md +64 -12
  4. data/docs/guides/core_concepts.md +65 -61
  5. data/docs/guides/decisions.md +69 -0
  6. data/docs/guides/embeddings.md +23 -0
  7. data/docs/guides/getting_started.md +38 -68
  8. data/docs/guides/integrations.md +20 -6
  9. data/docs/guides/models_and_providers.md +10 -29
  10. data/docs/guides/production.md +17 -4
  11. data/docs/guides/providers.md +58 -11
  12. data/lib/little_ghost/ag_ui/adapter.rb +64 -1
  13. data/lib/little_ghost/agent.rb +1 -1
  14. data/lib/little_ghost/agent_stream_source.rb +41 -2
  15. data/lib/little_ghost/assembly.rb +22 -18
  16. data/lib/little_ghost/assembly_builder.rb +2 -2
  17. data/lib/little_ghost/assembly_execution.rb +3 -1
  18. data/lib/little_ghost/code_mode/broker.rb +5 -3
  19. data/lib/little_ghost/code_mode/javascript/client.rb +1 -1
  20. data/lib/little_ghost/code_mode/javascript/session.rb +22 -2
  21. data/lib/little_ghost/code_mode/ruby/session.rb +15 -1
  22. data/lib/little_ghost/code_mode/session.rb +3 -0
  23. data/lib/little_ghost/decision.rb +230 -0
  24. data/lib/little_ghost/execution.rb +3 -1
  25. data/lib/little_ghost/graph.rb +3 -1
  26. data/lib/little_ghost/model.rb +5 -0
  27. data/lib/little_ghost/model_operations.rb +14 -0
  28. data/lib/little_ghost/provider_registry.rb +1 -0
  29. data/lib/little_ghost/providers/base.rb +5 -0
  30. data/lib/little_ghost/providers/decision_http.rb +91 -0
  31. data/lib/little_ghost/providers/gemini.rb +34 -8
  32. data/lib/little_ghost/providers/open_router.rb +18 -1
  33. data/lib/little_ghost/providers/typesafe.rb +35 -0
  34. data/lib/little_ghost/run.rb +23 -8
  35. data/lib/little_ghost/run_context.rb +21 -0
  36. data/lib/little_ghost/runtime.rb +8 -3
  37. data/lib/little_ghost/stream_event.rb +5 -2
  38. data/lib/little_ghost/swarm.rb +14 -48
  39. data/lib/little_ghost/version.rb +1 -1
  40. data/lib/little_ghost/workflow.rb +74 -96
  41. data/lib/little_ghost.rb +5 -0
  42. metadata +6 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 271908b0fc40900504fb25cd57d2cbcc8d987ac1ab32a0db58353562793446fc
4
- data.tar.gz: 507e5d747e8b341dd60b1edce8811e0dc5b2d41f98cb970e801284b2a326a49f
3
+ metadata.gz: a7758c8ce1e1ee404d86fe7dd76065dbd983a0abb660cedd82f7a6ffac0a3509
4
+ data.tar.gz: 485a32b90c723ed4a3c8b064151495e92d8679527f408d39e91145c2f3aaea09
5
5
  SHA512:
6
- metadata.gz: 830edf81e2d4892e7b72def07ba1d1be85843c8abf5cbb25d744ad520e8586fe9de2ae1cb32084ce832bb1eb866f4fa083af95b93e59df2b3e2c47f4e5c7aea9
7
- data.tar.gz: a8dba3d880bdc6adc4271daac984f9ab6384d34520a5be2071e66d1d746f4979952c13e7743364e2de2f2c2aa721057e12e54ca29c83a382b6506e49889ee43e
6
+ metadata.gz: bb412e0ec1ff688067bdbb14d34e62a72713f617a4d487188ca40ef2d05c2b3c18262b6b9da1e286a977f8251fb65b4818078d4a044c2d9566b1836876634b6e
7
+ data.tar.gz: c79396a4608f4643415a0ac50ca30f23e7a26cc5688a8ac593bf6674e7d8005185068c6e6107f205d53c834289a4aac390350f3e4e5deffea72d57ed76bddb19
data/README.md CHANGED
@@ -1,11 +1,16 @@
1
1
  # Build AI features that feel at home in Ruby
2
2
 
3
+ LittleGhost is a Ruby library for adding AI features to an existing application
4
+ or building a dedicated AI service. An **agent** combines a model with
5
+ instructions and Ruby operations it can call. Agents can work together in an
6
+ **assembly**, which your application calls like a single agent.
7
+
3
8
  > **Using a coding agent?** Start with
4
9
  > [`llms.txt`](https://littleghostai.org/llms.txt) for a concise map
5
10
  > of the guides and API. [`llms-full.txt`](https://littleghostai.org/llms-full.txt)
6
11
  > contains the complete documentation in one file.
7
12
 
8
- LittleGhost is a Ruby library for building AI features with agents and composable assemblies. With `OPENROUTER_API_KEY` set, start with one class, give it a prompt, and call it like the rest of your application code:
13
+ With the gem installed and `OPENROUTER_API_KEY` set, start with one class:
9
14
 
10
15
  ```ruby
11
16
  require "little_ghost"
@@ -68,7 +73,9 @@ The source checkout also includes a complete
68
73
  [single-file Agent](https://github.com/littleghostai/little_ghost/tree/main/examples/basic_agent)
69
74
  and
70
75
  [coding harness](https://github.com/littleghostai/little_ghost/tree/main/examples/coding_harness),
71
- both configured for local Ollama.
76
+ both configured for local Ollama. The
77
+ [decision example](https://github.com/littleghostai/little_ghost/tree/main/examples/decision)
78
+ shows typed questions with Jev through OpenRouter.
72
79
 
73
80
  ## Give an agent real capabilities
74
81
 
@@ -100,14 +107,13 @@ end
100
107
  The schema checks the shape of the input. Your Ruby code still decides whether
101
108
  the operation is allowed. The result goes back to the model as context.
102
109
 
103
- An ordinary Tool runs in your Ruby process. When a Tool needs files or child
104
- processes, it can delegate that work through a Sandbox. Code mode goes one step
105
- further: a sandboxed interpreter can compose several Tools, while every Tool
106
- call still returns to your Ruby Tool for validation and permission checks.
110
+ An ordinary Tool runs in your Ruby process. For operations that need files or
111
+ child processes, see [Workspaces and Sandboxes](docs/guides/sandboxing.md).
107
112
 
108
113
  ## Grow without changing the caller
109
114
 
110
- An **agent** owns one model loop. An **assembly** is one or more agents working as a unit. You call either one the same way:
115
+ When a task needs several agents, choose how they work together. These example
116
+ classes use different coordination styles, but their callers all use `.ask`:
111
117
 
112
118
  ```ruby
113
119
  CustomerSupportAgent.ask(question)
@@ -118,12 +124,12 @@ SupportFlowGraph.ask(question)
118
124
 
119
125
  Choose the coordination style that matches who should control the next step:
120
126
 
121
- - A **subagent** lets a model delegate an addressable task.
127
+ - A **subagent** is a specialist an agent can ask for help.
122
128
  - A **workflow** uses ordinary Ruby for ordering and branching.
123
129
  - A **swarm** lets configured agents choose permitted handoffs.
124
130
  - A **graph** makes allowed routes explicit as nodes and edges.
125
131
 
126
- A Workflow or Graph can contain agents, other assemblies, or both. Named classes are the clearest place to begin. Builders are there when your application discovers the participants or routes at runtime.
132
+ A Workflow or Graph can contain agents, other assemblies, or both.
127
133
 
128
134
  ```text
129
135
  request ──> CustomerSupportAgent
@@ -137,7 +143,9 @@ request ──> SupportFlowGraph ──> TriageAgent ──edge──> ResponseA
137
143
 
138
144
  The result stays familiar too. Every call returns a `Run` with the response,
139
145
  outcome, usage, and any final error. A coordinated assembly also records which
140
- participants ran. Use `.stream_ask` to watch the work as it happens.
146
+ participants ran. Use `.stream_ask` to watch the work as it happens and choose
147
+ which participants to display. [Getting Started](docs/guides/getting_started.md)
148
+ shows how to stream an Agent's answer and read the completed result.
141
149
 
142
150
  LittleGhost is pre-1.0. Pin the gem version and review release notes before
143
151
  upgrading, because interfaces may change between releases.
@@ -154,6 +162,8 @@ upgrading, because interfaces may change between releases.
154
162
  - [Structured Results and Content](docs/guides/structured_outputs_and_content.md) covers checked result shapes, images, and documents.
155
163
  - [Compose Agents](docs/guides/assemblies.md) walks through workflows, swarms, graphs, nesting, and builders.
156
164
  - [Skills](docs/guides/skills.md) organizes reusable instructions and supporting resources.
165
+ - [Decisions](docs/guides/decisions.md) explains typed questions and structured answers.
166
+ - [Embeddings](docs/guides/embeddings.md) explains text representations for similarity-based features.
157
167
  - [Workspaces and Sandboxes](docs/guides/sandboxing.md) gives files and child processes a deliberate place to run.
158
168
  - [Code Mode](docs/guides/code_mode.md) lets a model compose Tools in sandboxed Ruby or optional JavaScript.
159
169
  - [Integrations](docs/guides/integrations.md) connects Run streams to AG-UI and OpenTelemetry.
@@ -15,7 +15,12 @@ run = entrypoint.ask(question)
15
15
 
16
16
  ## Use a Workflow for explicit application logic
17
17
 
18
- A Workflow's `perform` method is ordinary Ruby. Inside it, `invoke` prepares a child call. Read `.output` when you need an intermediate answer. Return the final `invoke` call untouched so its response can stream to the caller, or return a value that Ruby computes from the intermediate answers.
18
+ A Workflow's `perform` method is ordinary Ruby. Inside it, `invoke` prepares a
19
+ child call. Read `.output` for its text or structured answer, or `.result` for
20
+ the complete `RunResult`. Return an invocation to select its answer as the
21
+ Workflow result. You can inspect that answer first, or return a value that Ruby
22
+ computes from intermediate answers. Every participating Agent publishes live
23
+ progress regardless of how you access or select results.
19
24
 
20
25
  ```ruby
21
26
  class ResponseWorkflow < LittleGhost::Workflow
@@ -41,7 +46,7 @@ Every participant passed to `invoke` can be an Agent or another Assembly. By def
41
46
 
42
47
  Each child Agent keeps its own [prompt view](prompt_views.md). The Workflow supplies request-specific input; it does not replace that Agent's reusable system instructions.
43
48
 
44
- The last child is special when its events should become the Workflow's public stream. Return that `invoke` without consuming it:
49
+ When one child should supply the final answer, return its invocation:
45
50
 
46
51
  ```ruby
47
52
  def perform
@@ -49,6 +54,38 @@ def perform
49
54
  end
50
55
  ```
51
56
 
57
+ To inspect an answer before selecting it, keep the invocation, read its output,
58
+ and return the same invocation after your checks. For example, given a
59
+ `ReviewAgent` whose structured result includes an `approved` boolean:
60
+
61
+ ```ruby
62
+ class ReviewedResponseWorkflow < LittleGhost::Workflow
63
+ private
64
+
65
+ def perform
66
+ candidate = invoke(CustomerSupportAgent)
67
+ review = invoke(ReviewAgent, input: candidate.output, history: [], context: {}).output
68
+
69
+ review.fetch("approved") ? candidate : invoke(EscalationAgent)
70
+ end
71
+ end
72
+ ```
73
+
74
+ Returning the candidate does not repeat the work or replay its text. The final
75
+ result preserves its conversation, state, and structured value. Usage and steps
76
+ include both the candidate and the review. Repeated `.result` or `.output` reads
77
+ reuse the completed result. An invocation must belong to the workflow returning
78
+ it and must complete successfully.
79
+
80
+ You can watch each Agent while the Workflow runs, including while an answer is
81
+ being reviewed. Reviewing an answer does not hide its progress. Choose which
82
+ participants your audience may see, as described in
83
+ [Watch every agent](#watch-every-agent-in-an-assembly).
84
+
85
+ Cancellation and deadlines apply before each child runs and before the Workflow
86
+ returns its answer. They also apply if a checkpoint callback cancels the run or
87
+ finishes after the deadline.
88
+
52
89
  When Ruby should compute the caller-visible result, consume every child and return the computed value:
53
90
 
54
91
  ```ruby
@@ -67,11 +104,11 @@ class EvidenceWorkflow < LittleGhost::Workflow
67
104
  end
68
105
  ```
69
106
 
70
- A returned String becomes the Workflow's textual response. Arrays, mappings, numbers, and booleans become a structured result available through `RunResult#output`, including when the Workflow is exposed with `assembly_as_tool`. Direct structured results must be JSON-compatible and stay within LittleGhost's structured-result size, depth, and complexity limits. Return an explicit value: `nil` remains a `ProtocolError`, which catches forgotten returns.
107
+ A returned String becomes the Workflow's textual response. Arrays, mappings, numbers, and booleans become a structured result available through `RunResult#output`, including when the Workflow is exposed with `assembly_as_tool`. Computed values appear in the final result, not as synthetic text-delta events. Direct structured results must be JSON-compatible and stay within LittleGhost's structured-result size, depth, and complexity limits. Return an explicit value: `nil` remains a `ProtocolError`, which catches forgotten returns.
71
108
 
72
109
  ### Choose a branch in Ruby
73
110
 
74
- Each branch should end with its final unconsumed invocation or a directly computed value:
111
+ Each branch should end with its final invocation or a directly computed value:
75
112
 
76
113
  ```ruby
77
114
  class RoutedResponseWorkflow < LittleGhost::Workflow
@@ -305,7 +342,9 @@ Retries start at zero. When `retries` is greater than zero, `retry_on` must list
305
342
 
306
343
  ## Watch every agent in an assembly
307
344
 
308
- Follow each participant while a composite assembly runs by handling its contextual `:agent_stream` events. These events arrive alongside the coherent public answer and assembly lifecycle events:
345
+ Follow each participant by handling source-tagged `:agent_stream` events. Every
346
+ Run uses this same progress channel, from one root Agent to nested assemblies
347
+ and subagents. Lifecycle events and the final result remain separate:
309
348
 
310
349
  ```ruby
311
350
  stream = SupportFlowGraph.stream_ask("Why was I charged twice?")
@@ -333,19 +372,31 @@ run.completed? # => true
333
372
 
334
373
  `source.agent_id` identifies the Agent class, `source.agent_path` distinguishes managed subagents, and `source.operation_id` groups one invocation. `source.assembly_path` lists the enclosing Workflow, Swarm, or Graph steps from the outside inward.
335
374
 
375
+ An Agent or Assembly invoked as a Tool within the Run adds a `:tool` step to that path. The
376
+ step identifies the invoking Agent and Tool name, and its descendants retain
377
+ the boundary. Tool-invoked Agents therefore remain distinct from the root
378
+ Agent even when their managed-subagent path is `/root`.
379
+
336
380
  The routed input and inner event are copied and frozen before they reach the
337
381
  observer, so changing an event can't affect the running assembly. Parallel
338
382
  participants can interleave. Events from each Agent retain their order, and
339
383
  LittleGhost never calls the stream block concurrently.
340
384
 
341
- The contextual wrapper arrives before the corresponding ordinary event. An assembly's final Agent therefore appears through both projections. Filter for `:agent_stream` when building an all-agent view, or handle ordinary events when rendering only the final answer. Pass `include_agent_events: false` when a composite assembly caller only wants the ordinary public stream. Standalone Agent streams keep their ordinary events by default and accept `include_agent_events: true` when source metadata is useful.
385
+ Agent progress appears only through `:agent_stream`, without duplicate raw
386
+ events. Returning an invocation selects its result; it does not replay that
387
+ Agent's progress. Handle the terminal Run event or read `run.result` for the
388
+ complete answer and aggregate usage. Pass `include_agent_events: false` to omit
389
+ all Agent progress without changing execution, lifecycle events, or results.
342
390
 
343
- The AG-UI adapter ignores contextual wrappers. Translate them explicitly if an AG-UI client should receive participant activity.
391
+ The [AG-UI adapter](integrations.md) displays root Agent progress by default.
392
+ Supply its `source_filter:` callable when a client should see selected assembly
393
+ participants.
344
394
 
345
- > **Safety note:** A composite stream can include inputs, reasoning, Tool
346
- > arguments and results, errors, and output from every participant. Check that
347
- > the destination may see the complete Run, or filter the events before sending
348
- > or storing them.
395
+ > **Safety note:** Every Run stream can include inputs, reasoning, Tool arguments
396
+ > and results, errors, and private output from nested participants. The example
397
+ > above observes the complete Run. Before sending or storing events for a
398
+ > narrower audience, select allowed sources and filter their fields. Result
399
+ > selection does not authorize disclosure of a participant's progress.
349
400
 
350
401
  ## Inspect what the assembly did
351
402
 
@@ -362,7 +413,8 @@ policy = trajectory.find { |step| step.participant == "policy" }
362
413
  trajectory.concurrent?(ledger.id, policy.id)
363
414
  ```
364
415
 
365
- Step outputs and buffered events have size limits. Use your application's
416
+ The trajectory retains step outputs, not a transcript of streaming events.
417
+ Step outputs and final results have size limits. Use your application's
366
418
  instrumentation when you need deeper diagnostics.
367
419
 
368
420
  ## Compose assemblies inside assemblies
@@ -1,6 +1,9 @@
1
1
  # Core Concepts
2
2
 
3
- Define an Agent in a Ruby class, then call it with `.ask`.
3
+ Start with an Agent: a Ruby class that gives a model instructions and operations
4
+ it can call. This guide builds on the help center example in
5
+ [Getting Started](getting_started.md), including its `HelpCenterLookupTool` and
6
+ provider setup.
4
7
 
5
8
  ```ruby
6
9
  class CustomerSupportAgent < LittleGhost::Agent
@@ -9,16 +12,20 @@ class CustomerSupportAgent < LittleGhost::Agent
9
12
  tools HelpCenterLookupTool
10
13
  end
11
14
 
12
- run = CustomerSupportAgent.ask("Where is my order?")
15
+ run = CustomerSupportAgent.ask("What is the refund policy?")
13
16
  run.response
14
17
  ```
15
18
 
16
19
  From there, add only what the work needs. Give the agent a tool. Let it ask a specialist for help. Or coordinate several agents while the rest of your application keeps making the same call.
17
20
 
18
- ## An Agent owns one model loop
21
+ ## An Agent carries a request through to an answer
19
22
 
20
23
  An **Agent** defines one model-driven behavior. It chooses the model, supplies the instructions and tools, and carries one request through to an answer.
21
24
 
25
+ The model can answer immediately or ask to call a Tool. LittleGhost runs the
26
+ Tool and sends its result back to the model, which can continue working. That
27
+ back-and-forth is the **model loop**.
28
+
22
29
  The class holds the behavior you want to reuse. Each call brings its own input, history, context, settings, and attachments. Request data never needs to live on the class.
23
30
 
24
31
  ```text
@@ -60,71 +67,32 @@ inside the Tool using identity and account information from your application.
60
67
  [Tools](tools.md) follows that path from model input to application code,
61
68
  including run-scoped bindings, concurrency, retries, and sandbox delegation.
62
69
 
63
- ## A Run owns one top-level execution
70
+ ## A Run records one request
64
71
 
65
72
  Every `.ask` or `.stream_ask` creates a **Run**. Think of it as the record of one trip through LittleGhost. It opens what the request needs, records how the work ended, and closes the resources it owns.
66
73
 
67
74
  ```ruby
68
- run = CustomerSupportAgent.ask("Where is order 481?")
75
+ run = CustomerSupportAgent.ask("What is the refund policy?")
69
76
 
70
77
  run.completed? # => true
71
78
  run.response
72
- # One possible response: Order 481 is out for delivery.
73
- run.usage # => normalized token usage
79
+ # One possible response: Refunds are available within 30 days.
80
+ run.usage # Token counts reported by the model provider.
74
81
  run.result # => the complete LittleGhost::RunResult
75
82
  ```
76
83
 
77
84
  The Agent defines reusable behavior; the Run records what happened this time.
78
85
 
79
- ### Follow one request
80
-
81
- One Run owns the trip from request to result:
82
-
83
- ```text
84
- Run
85
- ├── Invocation: caller input, history, and application context
86
- ├── RunContext: mutable working state for this execution
87
- └── Agent and Tools ──> RunResult
88
- ```
89
-
90
- An **Invocation** is the request in LittleGhost's standard shape. Its `context`
91
- contains current request values supplied by your application. A Tool can read
92
- those values through `run.invocation.context` when it checks permission.
93
-
94
- A **Session** stores conversation state between Runs when persistence is
95
- configured. The **RunContext** carries mutable working state in `context.state`
96
- during one Run. LittleGhost loads saved Session state before adding the current
97
- Invocation context. Recheck saved values before using them for permission
98
- decisions.
99
-
100
- A Tool's **Binding** gives the Tool access to objects created for this run,
101
- including the Agent, Run, Workspace, and Sandbox. These objects are separate
102
- from arguments chosen by the model. [Tools](tools.md) explains the binding;
103
- [Workspaces and Sandboxes](sandboxing.md) explains delegated files and child
104
- processes.
105
-
106
- The final **RunResult** keeps the complete assembly result. Its `text` is the final text answer. Its `output` returns structured data when the Agent declared a result schema, and text otherwise. The top-level `Run#response` is always the caller-facing text.
107
-
108
- ### See how a call ended
109
-
110
- Top-level calls normally return a Run, even when execution fails. The terminal event carries the same outcome when you stream:
86
+ The final **RunResult**, available through `run.result`, holds the answer and
87
+ details such as token usage. Its `output` returns text unless you configured
88
+ the Agent to return checked data, such as a hash of named fields. See
89
+ [Structured Results and Content](structured_outputs_and_content.md) for that
90
+ alternative. Use `run.response` when you want the text answer.
111
91
 
112
- | What happened | Run outcome | Terminal event | What Ruby does |
113
- | --- | --- | --- | --- |
114
- | The assembly completed | `completed` | `:run_stop` | Returns the Run |
115
- | Model, provider, or assembly execution failed | `failed` | `:run_error` | Returns the Run; inspect `run.error` |
116
- | The deadline stopped work | `partial` | `:run_partial` | Returns the Run with any response produced so far |
117
- | Cancellation stopped work | `cancelled` | `:run_cancel` | Returns the Run without a response |
118
- | Tool input or a `ToolError` failed | The model may recover | No terminal event by itself | Gives a safe error result back to the model |
119
- | Input, configuration, or resources failed before a Run could start | No Run exists | None | Raises the exception |
120
-
121
- Unexpected Tool exception messages are hidden from the model. The original
122
- exception remains available to application callbacks and diagnostics.
123
-
124
- Failures while closing resources, delivering events, or reporting
125
- instrumentation sit outside the normal result path. They raise a Ruby exception
126
- because LittleGhost can no longer promise that it delivered a clean ending.
127
- [Running in Production](production.md) covers supervision and shutdown.
92
+ When a Tool needs to know who is asking, pass information from your application
93
+ with the request. [Tools](tools.md) explains how it reaches the Tool. When a
94
+ conversation should continue across requests, a **Session** saves its history
95
+ and working state; [Running in Production](production.md) covers that setup.
128
96
 
129
97
  ## An Assembly can look like one Agent
130
98
 
@@ -157,6 +125,10 @@ The coordination types differ mainly in who decides what happens next:
157
125
 
158
126
  A **subagent** is a specialist that a parent Agent can call for help. The parent model chooses when to delegate, reads the result, and then continues its own answer.
159
127
 
128
+ The examples below omit the specialist Agent definitions. Each is an Agent
129
+ class like `CustomerSupportAgent`, with instructions and tools suited to its
130
+ task. [Compose Agents](assemblies.md) expands on these coordination patterns.
131
+
160
132
  ```ruby
161
133
  class CustomerSupportAgent < LittleGhost::Agent
162
134
  model "openrouter:openai/gpt-5.6-luna"
@@ -166,15 +138,13 @@ end
166
138
 
167
139
  Use a subagent when delegation is part of one model's decision-making. Use a Workflow when application code must guarantee that a step happens.
168
140
 
169
- When an Agent also uses code mode, subagent controls stay in the Agent's
170
- conversation. Code-mode programs can compose ordinary Tools, while spawning,
171
- messaging, and checking on subagents remain decisions for the parent model.
172
-
173
141
  ### Workflows make Ruby the coordinator
174
142
 
175
143
  A **Workflow** coordinates work with ordinary Ruby. Its `perform` method can call an Agent or another Assembly, read a result, choose a branch, or run independent steps together.
176
144
 
177
- `invoke` prepares a lazy child call. Reading `.output` runs an intermediate child. Return the final `invoke` itself, without reading its output, so that answer can stream to the caller.
145
+ `invoke` prepares a participant's call without running it yet. Read `.output`
146
+ to run it and use its answer in Ruby. Return the final `invoke` call to use
147
+ that participant's answer as the Workflow's result.
178
148
 
179
149
  ```ruby
180
150
  class ResponseWorkflow < LittleGhost::Workflow
@@ -192,6 +162,13 @@ class ResponseWorkflow < LittleGhost::Workflow
192
162
  end
193
163
  ```
194
164
 
165
+ In this example, research finishes before the support Agent begins. `input.text`
166
+ is the original question; the Workflow adds the research to it.
167
+
168
+ You can also inspect an answer before choosing it as the final result, without
169
+ running the participant again. [Compose Agents](assemblies.md) shows how, along
170
+ with ways to display each participant's progress.
171
+
195
172
  Workflow children receive the caller's history and application context by default. Pass `history: []`, `context: {}`, or redacted values when a participant should receive less.
196
173
 
197
174
  ### Swarms let agents hand work to one another
@@ -216,7 +193,8 @@ Agent should use it as context rather than proof that an action is permitted.
216
193
 
217
194
  ### Graphs make routes visible
218
195
 
219
- A **Graph** connects named Assembly nodes with declared edges. Nodes can contain Agents, Workflows, Swarms, or other Graphs.
196
+ A **Graph** lays out the steps and routes through a task. Each named **node**
197
+ runs an Agent or another Assembly. An **edge** says which node can run next.
220
198
 
221
199
  ```ruby
222
200
  class SupportFlowGraph < LittleGhost::Graph
@@ -236,6 +214,10 @@ class SupportFlowGraph < LittleGhost::Graph
236
214
  end
237
215
  ```
238
216
 
217
+ Here, `TriageAgent` is expected to answer `billing` for billing questions.
218
+ That answer selects the conditional billing route. Otherwise, the unconditional
219
+ general route is the fallback; it does not run alongside the billing route.
220
+
239
221
  Graph nodes receive the original task and results from the nodes immediately
240
222
  before them. They do not receive caller history or application context unless
241
223
  their declarations opt in. [Compose Agents](assemblies.md) explains parallel
@@ -256,6 +238,28 @@ run.result.trajectory.transitions
256
238
  This record shows which participants ran. [Compose Agents](assemblies.md)
257
239
  explains builders, detailed routing records, and live events from nested Agents.
258
240
 
241
+ ## Handle the outcome
242
+
243
+ An Agent or coordinated Assembly normally returns a Run even when the work
244
+ fails. Check its outcome before using the answer:
245
+
246
+ | What happened | Run outcome | What to inspect |
247
+ | --- | --- | --- |
248
+ | Work completed | `completed` | `run.response` or `run.result` |
249
+ | Model, provider, or assembly execution failed | `failed` | `run.error` |
250
+ | The deadline stopped work | `partial` | Any response produced so far |
251
+ | Cancellation stopped work | `cancelled` | No response is returned |
252
+
253
+ A Tool error need not end the Run: LittleGhost can give the model a safe error
254
+ result so it can try again. Unexpected exception messages stay in application
255
+ diagnostics rather than going to the model.
256
+
257
+ Some failures raise Ruby exceptions instead of returning a Run, including
258
+ invalid setup before work starts and failures while closing resources or
259
+ delivering events. [Running in Production](production.md) covers error handling
260
+ and shutdown; [Run](rdoc-ref:LittleGhost::Run) lists the streaming events for
261
+ each outcome.
262
+
259
263
  The pieces now fit together: Agents define behavior. Tools connect them to Ruby. Runs record one execution. Assemblies let the system grow without changing the caller.
260
264
 
261
265
  Continue with [Models and Providers](models_and_providers.md) to choose model
@@ -0,0 +1,69 @@
1
+ # Decisions
2
+
3
+ Use a decision model when an application needs typed answers to a small set of
4
+ questions. `LittleGhost.decide` returns the answers and token usage without
5
+ starting an Agent or creating a Run. Jev supports Choice, Score, and Noul
6
+ (yes/no probability) questions:
7
+
8
+ ```ruby
9
+ result = LittleGhost.decide(
10
+ model: "primary:~typesafe/jev-latest",
11
+ state: {payout_status: "failed", failed_days: 3},
12
+ questions: [
13
+ {
14
+ id: "route",
15
+ type: :choice,
16
+ instructions: "Choose a route",
17
+ criteria: {
18
+ review: "Needs more investigation",
19
+ approve: "Meets the criteria",
20
+ decline: "Does not meet the criteria"
21
+ }
22
+ },
23
+ {id: "urgent", type: :noul, instructions: "Does this need same-day attention?"}
24
+ ]
25
+ )
26
+
27
+ result.answers.fetch("route").choice
28
+ result.answers.fetch("urgent").noul
29
+ ```
30
+
31
+ Choice answers contain the selected label. Noul answers contain the
32
+ probability of yes from 0 to 1. Score answers contain a probability-weighted
33
+ value across the declared levels. Choice and Score answers also include the
34
+ probability distribution and confidence; Score answers include the level
35
+ legend.
36
+
37
+ For reusable decisions, declare questions once on a `Decision` class. A class
38
+ can mix question types:
39
+
40
+ ```ruby
41
+ class ApplicationTriage < LittleGhost::Decision
42
+ model "primary:~typesafe/jev-latest"
43
+ choice :route, instructions: "Choose a route", criteria: {
44
+ review: "Needs more investigation",
45
+ approve: "Meets the criteria",
46
+ decline: "Does not meet the criteria"
47
+ }
48
+ noul :urgent, instructions: "Does this need same-day attention?"
49
+ score :quality, instructions: "Rate the quality", criteria: ["accuracy", "completeness"]
50
+ end
51
+
52
+ application_state = {payout_status: "failed", failed_days: 3}
53
+ result = ApplicationTriage.ask(application_state)
54
+ result.answers.fetch("quality").score
55
+ ```
56
+
57
+ The class-level `.ask` and an instance's `#ask` return
58
+ `LittleGhost::DecisionResult`. Read a typed value with
59
+ `LittleGhost::DecisionAnswer#value` or its type-specific reader (`choice`,
60
+ `noul`, or `score`).
61
+
62
+ The selected provider receives the state and question text. Choose a provider
63
+ that is appropriate for that data.
64
+
65
+ Decisions require a TypeSafe connection or an OpenRouter connection configured
66
+ for a Jev decision endpoint. Other providers raise
67
+ `UnsupportedModelOperationError`. See [Provider Support](providers.md) for
68
+ connection setup and [Models and Providers](models_and_providers.md) for model
69
+ targets, shared roles, and capabilities.
@@ -0,0 +1,23 @@
1
+ # Embeddings
2
+
3
+ Use `LittleGhost.embed` to turn text into numeric representations for search,
4
+ clustering, or another similarity-based feature:
5
+
6
+ ```ruby
7
+ response = LittleGhost.embed(
8
+ model: "primary:openai/text-embedding-3-small",
9
+ inputs: ["Reset a password", "Track a transfer"]
10
+ )
11
+
12
+ response.vectors.length # => 2
13
+ response.dimensions
14
+ response.usage.input_tokens
15
+ ```
16
+
17
+ The response keeps vectors in the same order as the inputs. LittleGhost rejects
18
+ an incomplete or malformed response instead of returning a partial batch.
19
+ Embedding text is sent to the selected provider, so choose one appropriate for
20
+ that data. [Provider Support](providers.md) identifies adapters with embedding
21
+ support; `LittleGhost::Embeddings::Request` documents settings and request
22
+ bounds. See [Models and Providers](models_and_providers.md) for model targets,
23
+ shared roles, and capabilities.