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.
- checksums.yaml +4 -4
- data/README.md +20 -10
- data/docs/guides/assemblies.md +64 -12
- data/docs/guides/core_concepts.md +65 -61
- data/docs/guides/decisions.md +69 -0
- data/docs/guides/embeddings.md +23 -0
- data/docs/guides/getting_started.md +38 -68
- data/docs/guides/integrations.md +20 -6
- data/docs/guides/models_and_providers.md +10 -29
- data/docs/guides/production.md +17 -4
- data/docs/guides/providers.md +58 -11
- data/lib/little_ghost/ag_ui/adapter.rb +64 -1
- data/lib/little_ghost/agent.rb +1 -1
- data/lib/little_ghost/agent_stream_source.rb +41 -2
- data/lib/little_ghost/assembly.rb +22 -18
- data/lib/little_ghost/assembly_builder.rb +2 -2
- data/lib/little_ghost/assembly_execution.rb +3 -1
- data/lib/little_ghost/code_mode/broker.rb +5 -3
- data/lib/little_ghost/code_mode/javascript/client.rb +1 -1
- data/lib/little_ghost/code_mode/javascript/session.rb +22 -2
- data/lib/little_ghost/code_mode/ruby/session.rb +15 -1
- data/lib/little_ghost/code_mode/session.rb +3 -0
- data/lib/little_ghost/decision.rb +230 -0
- data/lib/little_ghost/execution.rb +3 -1
- data/lib/little_ghost/graph.rb +3 -1
- data/lib/little_ghost/model.rb +5 -0
- data/lib/little_ghost/model_operations.rb +14 -0
- data/lib/little_ghost/provider_registry.rb +1 -0
- data/lib/little_ghost/providers/base.rb +5 -0
- data/lib/little_ghost/providers/decision_http.rb +91 -0
- data/lib/little_ghost/providers/gemini.rb +34 -8
- data/lib/little_ghost/providers/open_router.rb +18 -1
- data/lib/little_ghost/providers/typesafe.rb +35 -0
- data/lib/little_ghost/run.rb +23 -8
- data/lib/little_ghost/run_context.rb +21 -0
- data/lib/little_ghost/runtime.rb +8 -3
- data/lib/little_ghost/stream_event.rb +5 -2
- data/lib/little_ghost/swarm.rb +14 -48
- data/lib/little_ghost/version.rb +1 -1
- data/lib/little_ghost/workflow.rb +74 -96
- data/lib/little_ghost.rb +5 -0
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a7758c8ce1e1ee404d86fe7dd76065dbd983a0abb660cedd82f7a6ffac0a3509
|
|
4
|
+
data.tar.gz: 485a32b90c723ed4a3c8b064151495e92d8679527f408d39e91145c2f3aaea09
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
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.
|
|
104
|
-
processes,
|
|
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
|
-
|
|
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**
|
|
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.
|
|
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.
|
data/docs/guides/assemblies.md
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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:**
|
|
346
|
-
>
|
|
347
|
-
>
|
|
348
|
-
>
|
|
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
|
-
|
|
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
|
-
|
|
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("
|
|
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
|
|
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
|
|
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("
|
|
75
|
+
run = CustomerSupportAgent.ask("What is the refund policy?")
|
|
69
76
|
|
|
70
77
|
run.completed? # => true
|
|
71
78
|
run.response
|
|
72
|
-
# One possible response:
|
|
73
|
-
run.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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
|
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**
|
|
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.
|