You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
description: Use ralphify as a Python library — run loops programmatically, listen to events, manage multiple runs, and discover primitives without the CLI.
2
+
description: Use ralphify as a Python library — run loops programmatically, listen to events, and discover primitives without the CLI.
3
3
---
4
4
5
5
# Python API
6
6
7
-
Ralphify can be used as a Python library, not just a CLI. This is useful when you want to:
7
+
Ralphify can be used as a Python library. This is useful when you want to embed the loop in a larger automation pipeline, react to events programmatically, or script runs with more control than the CLI provides.
8
8
9
-
- Embed the loop in a larger automation pipeline
10
-
- Build custom orchestration on top of ralphify
11
-
- Listen to events and react programmatically (e.g. send Slack alerts on failures)
12
-
- Script runs with more control than the CLI provides
9
+
All public API is available from the top-level `ralphify` package.
13
10
14
11
## Quick start
15
12
@@ -26,58 +23,28 @@ state = RunState(run_id="my-run")
26
23
run_loop(config, state)
27
24
```
28
25
29
-
This runs the same loop as `ralph run -n 3`, using `RALPH.md` as the prompt. When the loop finishes, `state` contains the results.
26
+
This runs the same loop as `ralph run -n 3`. When the loop finishes, `state` contains the results.
30
27
31
-
## Core function
28
+
## `run_loop(config, state, emitter=None)`
32
29
33
-
### `run_loop(config, state, emitter=None)`
34
-
35
-
The main loop. Discovers primitives, assembles prompts, pipes them to the agent, runs checks, and repeats.
36
-
37
-
```python
38
-
from ralphify import run_loop, RunConfig, RunState, NullEmitter
39
-
40
-
config = RunConfig(
41
-
command="claude",
42
-
args=["-p", "--dangerously-skip-permissions"],
43
-
prompt_file="RALPH.md",
44
-
max_iterations=5,
45
-
stop_on_error=True,
46
-
timeout=300,
47
-
log_dir="ralph_logs",
48
-
)
49
-
state = RunState(run_id="build-features")
50
-
51
-
run_loop(config, state)
52
-
53
-
print(f"Completed: {state.completed}")
54
-
print(f"Failed: {state.failed}")
55
-
print(f"Total: {state.total}")
56
-
```
30
+
The main loop. Discovers primitives, assembles prompts, pipes them to the agent, runs checks, and repeats. Blocks until the loop finishes.
57
31
58
32
| Parameter | Type | Description |
59
33
|---|---|---|
60
34
|`config`|`RunConfig`| All settings for the run |
61
35
|`state`|`RunState`| Observable state — counters, status, control methods |
@@ -193,181 +103,34 @@ state = RunState(run_id="observed-run")
193
103
run_loop(config, state, emitter=MyEmitter())
194
104
```
195
105
196
-
### `Event`
197
-
198
-
Every event has these fields:
199
-
200
-
| Field | Type | Description |
201
-
|---|---|---|
202
-
|`type`|`EventType`| What happened |
203
-
|`run_id`|`str`| Which run produced this event |
204
-
|`data`|`dict`| Event-specific data |
205
-
|`timestamp`|`datetime`| UTC timestamp |
206
-
207
-
Use `event.to_dict()` to serialize for JSON transport.
208
-
209
-
### `EventType`
210
-
211
-
Events cover the full run lifecycle: `RUN_STARTED`, `RUN_STOPPED`, `RUN_PAUSED`, `RUN_RESUMED`, iteration events (`ITERATION_STARTED`, `ITERATION_COMPLETED`, `ITERATION_FAILED`, `ITERATION_TIMED_OUT`), check events (`CHECKS_STARTED`, `CHECK_PASSED`, `CHECK_FAILED`, `CHECKS_COMPLETED`), prompt assembly (`CONTEXTS_RESOLVED`, `PROMPT_ASSEMBLED`), and streaming (`AGENT_ACTIVITY`, `LOG_MESSAGE`).
212
-
213
-
Each event's `data` dict contains relevant fields (iteration number, exit codes, durations, output text, etc.). Inspect `event.data.keys()` or see the `EventType` enum in source for the full schema.
214
-
215
-
### Built-in emitters
216
-
217
-
| Emitter | Description | Use case |
218
-
|---|---|---|
219
-
|`NullEmitter`| Discards all events | Tests, silent runs |
220
-
|`QueueEmitter`| Pushes events into a `queue.Queue`| Async consumers, UI layers |
Each `Event` has `type` (`EventType`), `run_id`, `data` (dict), and `timestamp`. Use `event.to_dict()` to serialize.
272
107
273
-
`RunManager` provides `create_run(config)`, `start_run(run_id)`, `stop_run(run_id)`, `pause_run(run_id)`, `resume_run(run_id)`, `list_runs()`, and `get_run(run_id)`. Each run is wrapped in a `ManagedRun` with `config`, `state`, `emitter` (QueueEmitter), and `thread` fields. Use `managed.add_listener(emitter)` to register additional event listeners before starting.
108
+
Built-in emitters: `NullEmitter` (silent), `QueueEmitter` (pushes to a `queue.Queue`), `FanoutEmitter` (broadcasts to multiple emitters).
274
109
275
110
## Primitive discovery
276
111
277
-
Discover checks, contexts, instructions, and ralphs without running the loop.
112
+
Discover checks, contexts, instructions, and ralphs without running the loop:
278
113
279
114
```python
280
115
from pathlib import Path
281
116
from ralphify import discover_checks, discover_contexts, discover_instructions, discover_ralphs
0 commit comments