agent_c 2.9979 → 2.71828

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24e17363e73084fdbcf50fda975a5822e622a80c04b0822e4017dfe02f46240a
4
- data.tar.gz: fe16a11e5ac880e18f5bc4c0317d2b8f7386542de99aec3217c06af8e4625186
3
+ metadata.gz: 8321a1602d20f566b59365d641fecb934340b043d6544e43b01b2951e947282b
4
+ data.tar.gz: bf3cd0d58944294f4e83e080ac7aebfff8677798c96426411e559c8f7e7f6a7d
5
5
  SHA512:
6
- metadata.gz: 6937e2b0cdb4c9db5b5aca19e2093ed1810ff2ed058baec3f017ab7f32c567726020d98973c2ca277bbd4ea653325afd6934555113bd25cbec8ad03e79a66431
7
- data.tar.gz: 2649e8a916012ff96ff200d2b749e376137dbee4e59cec89fbfc244d42226acc67c2b5812483dda14e3d815126ae14030eb488ef7b70db738a89d927a20cf1b3
6
+ metadata.gz: 5dbe7a3d1ca921db961a5a3685c01f4e539b0358506cb45f9d6a04c462cb0657efa45eff16eea4f65c00bdb6f113b40551b38e71f5d61ceadf8463cec1ea9007
7
+ data.tar.gz: 4b407bc2cf7086536bce703b209552b8753c6b3eef37b096437728095945d247a5b6643113487ad739339e407b6e4c43c6b0cdd72aeca3f75551ab9e1ac763e0
data/CLAUDE.md CHANGED
@@ -8,7 +8,7 @@
8
8
  - DO NOT add example scripts. Either add it to the readme or make a test.
9
9
  - DO NOT add documentation outside of the README
10
10
  - DO NOT program defensively. If something should respond_to?() a method then just invoke the method. An error is better than a false positive
11
- - DO NOT write a one-off script for debugging, write a test-case and run it instead.
11
+ - If you need to test a one-off script, write a test-case and run it instad of writing a temporary file or using a giant shell script
12
12
  - DO NOT edit the singleton class of an object. If you think you need to do this, ideas for avoiding: inject an object, create a module and include it, make a base class.
13
13
 
14
14
  # TESTING
data/README.md CHANGED
@@ -336,7 +336,7 @@ I suggest following the structure of the [example template](./template).
336
336
 
337
337
  Detailed guides for all features:
338
338
 
339
- - **[Batch](docs/batch.md)** - Batch configuration, methods, and pipeline integration
339
+ - **[Main README](../README.md)** - Batch and Pipeline usage (primary approach)
340
340
  - **[Pipeline Tips and Tricks](docs/pipeline-tips-and-tricks.md)** - Useful patterns and techniques for pipelines
341
341
  - **[Chat Methods](docs/chat-methods.md)** - Using session.prompt and session.chat for direct interactions
342
342
  - **[Tools](docs/tools.md)** - Built-in tools for file operations and code interaction
data/TODO.md CHANGED
@@ -5,101 +5,8 @@ Things I'd like to work on:
5
5
  - Make injecting a Chat record simpler.
6
6
  - Make injecting Git simpler (make injecting anything easier)
7
7
  - Add a request queue to AgentC::Chat so that we can rate-limit and retry on error
8
- - Use spring for run_rails_test, but add a timeout condition where it kills the process if no stdout appears for a while and tries again without spring.
9
- - tool calls should write the full results to file (except for readfile) and pass back a reference for future queries. For example, if RunRailsTest gives way too much output, we have to truncate but how to see the rest?
10
-
11
- ## Immplement plan, implement, review looping
12
-
13
- Some scratch:
14
-
15
- ```ruby
16
- agent_iterate_loop(
17
- :implement_query_object,
18
- max_tries: 17,
19
- plan: [
20
- :plan_step_1,
21
- :plan_step_2,
22
- ],
23
- implement: [
24
- :implement_step_1,
25
- :implement_step_2,
26
- ],
27
- # optional: defaults to implement
28
- iterate: [
29
- :address_feedback_1
30
- ]
31
- review: [
32
- :review_step_1,
33
- :review_step_2
34
- ],
35
- )
36
- ```
37
-
38
- Thoughts:
39
-
40
- - This makes a demand on the `response_schema` of the prompts.
41
- - Does the `task` track the looping here or the `record`?
42
- - Is the progress tracked in memory? This can be one step...
43
- - What if you have multiple `agent_iterate_loop` invocations? How do we store diffs/reviews for each of those?
44
- - The `agent_step` applies the result to the record. If we track it on the task, we could get the attributes to the right place. Can we extend the response schema? The `plan` step definitely needs to update the record, so it needs to specify response_schema. The `implement/iterate` steps *might* need to accept response_schema (eg, path of file created? Or not necessary?, maybe not necessary.)
45
- - Does a failed review trigger plan -> iterate -> review or just iterate -> review
46
- - The implement/iterate arrays could include "plan" steps so that they know if they're starting from scratch or not.
47
- - Do we run every review or stop at the first one?
48
-
49
-
50
- ```ruby
51
- def agent_iterate_loop(
52
- name,
53
- max_tries: 3,
54
- implement: [],
55
- iterate: implement,
56
- review: [],
57
- )
58
- step(name) do
59
- tries = 0
60
-
61
- while(tries < max_tries)
62
- if tries == 0
63
- implement.each do |name|
64
- process_prompt(name)
65
- end
66
- else
67
- iterate.each do |name|
68
- process_prompt(
69
- name,
70
- additional_i18n_attrs: {
71
- feedback: feedback.join("\n---\n")
72
- }
73
- )
74
- end
75
- end
76
-
77
- feedbacks = []
78
-
79
- diff = git.diff
80
- review.each do |name|
81
- result = process_prompt(
82
- name,
83
- schema: -> {
84
- t.boolean(:pass)
85
- t.string(:feedback)
86
- },
87
- additional_i18n_attrs: {
88
- diff:
89
- }
90
- )
91
-
92
- if !result.fetch("pass")
93
- feedbacks << result.fetch("feedback")
94
- end
95
- end
96
-
97
- if record.respond_to?(:add_review)
98
- record.add_review(diff:, feedbacks:)
99
- end
100
-
101
- break if feedbacks.empty?
102
- end
103
- end
104
- end
105
- ```
8
+ - Use spring for run_rails_test, but add a timeout condition where it kills the
9
+ process if no stdout appears for a while and tries again without spring.
10
+ - tool calls should write the full results to file (except for readfile) and pass
11
+ back a reference for future queries. For example, if RunRailsTest gives way too
12
+ much output, we have to truncate but how to see the rest?
data/docs/chat-methods.md CHANGED
@@ -43,14 +43,15 @@ answer = chat.get("What is 2 + 2?")
43
43
  # give a reason why.
44
44
  #
45
45
  # The response will look like one of the following:
46
- # Success response (just the data fields):
47
46
  # {
47
+ # status: "success",
48
48
  # name: "...",
49
49
  # email: "...",
50
50
  # }
51
- # OR error response:
51
+ # OR:
52
52
  # {
53
- # unable_to_fulfill_request_error: "some reason why it couldn't do it"
53
+ # status: "failure",
54
+ # message: "some reason why it couldn't do it"
54
55
  # }
55
56
 
56
57
  schema = AgentC::Schema.result do
@@ -62,10 +63,10 @@ result = chat.get(
62
63
  "Extract the name and email from this text: 'Contact John at john@example.com'",
63
64
  schema: schema
64
65
  )
65
- # => { "name" => "John", "email" => "john@example.com" }
66
+ # => { "status" => "success", "name" => "John", "email" => "john@example.com" }
66
67
 
67
68
  # If the LLM can't complete the task, it returns an error response:
68
- # => { "unable_to_fulfill_request_error" => "No email found in the text" }
69
+ # => { "status" => "error", "message" => "No email found in the text" }
69
70
  ```
70
71
 
71
72
  ### Using confirm and out_of for consensus
@@ -2,12 +2,6 @@
2
2
 
3
3
  This document contains useful patterns and techniques for working with AgentC pipelines.
4
4
 
5
- ## Index
6
-
7
- - [Custom I18n Attributes](#custom-i18n-attributes)
8
- - [Rewinding to Previous Steps](#rewinding-to-previous-steps)
9
- - [Agent Review Loop](#agent-review-loop)
10
-
11
5
  ## Custom I18n Attributes
12
6
 
13
7
  By default, when using i18n interpolation in your prompts, AgentC will use `record.attributes` to provide values for interpolation. However, you can customize this behavior by implementing an `i18n_attributes` method on your record.
@@ -75,379 +69,3 @@ agent_step(:my_step)
75
69
  ### Return Value
76
70
 
77
71
  The `i18n_attributes` method should return a Hash with symbol or string keys. These keys will be used for interpolation in your i18n strings.
78
-
79
- ## Rewinding to Previous Steps
80
-
81
- The `rewind_to!` method allows you to restart execution from a previously completed step. This is useful when you need to retry or re-execute steps based on runtime conditions.
82
-
83
- ### Use Case
84
-
85
- This is useful when:
86
- - An agent determines that a previous step needs to be re-executed
87
- - You want to implement retry logic based on validation results
88
- - You need to loop through steps until certain conditions are met
89
- - A later step discovers that earlier work needs to be redone
90
-
91
- ### Basic Usage
92
-
93
- ```ruby
94
- class Store < AgentC::Store
95
- record(:refactor) do
96
- schema do
97
- t.boolean(
98
- :review_passed,
99
- default: false
100
- )
101
-
102
- t.string(
103
- :review_feedback,
104
- default: "none"
105
- )
106
- end
107
- end
108
- end
109
-
110
- class MyPipeline < AgentC::Pipeline
111
- # prompt:
112
- # Perform the refactor.
113
- # Here is feedback from the reviewer (if any):
114
- # %{review_feedback}
115
- agent_step(:perform_refactor)
116
-
117
- # capture the diff
118
- step(:capture_diff) do
119
- record.update!(diff: git.diff)
120
- end
121
-
122
- # prompt:
123
- # Review this diff: %{diff}
124
- # schema:
125
- # review_passed:
126
- # type: boolean
127
- # review_feedback:
128
- # type: string
129
- agent_step(:review_refactor)
130
-
131
- step(:verify_output) do
132
- # if the review hasn't passed,
133
- # then review_feedback is now
134
- # present and will be passed
135
- # back in to refactor step above
136
- unless record.review_passed
137
- rewind_to!(:perform_refactor)
138
- end
139
- end
140
- end
141
- ```
142
-
143
- ### How It Works
144
-
145
- When you call `rewind_to!(step_name)`, the pipeline:
146
- 1. Validates that the specified step has already been completed
147
- 2. Validates that the step name appears only once in `completed_steps`
148
- 3. Removes the specified step and all subsequent steps from `completed_steps`
149
- 4. Continues execution from the rewound step
150
-
151
- ### Important Notes
152
-
153
- **Infinite loops**: There's no automatic infinite loop detection. Use your record's state to count rewinds if you are concerned about a potential infinite loop.
154
-
155
- **Must be called from within a step**: The `rewind_to!` method must be invoked from within a pipeline step during execution.
156
-
157
- **Step must be completed**: You can only rewind to steps that have already been completed in the current pipeline run. Attempting to rewind to a step that hasn't been completed will raise an `ArgumentError`.
158
-
159
- **Step must be unique**: If a step name appears multiple times in `completed_steps`, attempting to rewind to it will raise an `ArgumentError`. This prevents ambiguous rewind operations.
160
-
161
- **State considerations**: When rewinding, be aware that any side effects from the original execution of the rewound steps will remain unless explicitly cleaned up. The pipeline doesn't automatically rollback database changes or other state modifications.
162
-
163
- ### Example: Retry Logic
164
-
165
- ```ruby
166
- class ProcessWithRetry < AgentC::Pipeline
167
- step(:attempt_processing) do
168
- result = process_with_agent
169
- record.update!(
170
- attempt_count: record.attempt_count + 1,
171
- last_result: result
172
- )
173
- end
174
-
175
- step(:check_result) do
176
- if record.last_result.failed? && record.attempt_count < 3
177
- # Retry by going back to the processing step
178
- rewind_to!(:attempt_processing)
179
- elsif record.last_result.failed?
180
- task.fail!("Failed after 3 attempts")
181
- else
182
- record.update!(status: "completed")
183
- end
184
- end
185
- end
186
- ```
187
-
188
- ### Error Handling
189
-
190
- If you try to rewind to a step that hasn't been completed yet:
191
-
192
- ```ruby
193
- step(:early_step) do
194
- rewind_to!(:later_step) # ArgumentError: Cannot rewind to a step that's not been completed yet
195
- end
196
- ```
197
-
198
- If a step name appears multiple times in `completed_steps`:
199
-
200
- ```ruby
201
- # This will raise an ArgumentError about non-distinct step names
202
- rewind_to!(:duplicate_step)
203
- ```
204
-
205
- ## Agent Review Loop
206
-
207
- The `agent_review_loop` method provides a declarative way to implement iterative review and refinement workflows. It automatically handles the loop logic where an agent implements a solution, reviewers provide feedback, and the agent iterates based on that feedback until the reviewers approve or a maximum number of tries is reached.
208
-
209
- ### Use Case
210
-
211
- This is useful when:
212
- - You need an agent to generate code, designs, or content that requires review
213
- - Multiple reviewers need to evaluate the work from different perspectives
214
- - The agent should iterate based on feedback until reviewers approve
215
- - You want to capture review history for audit or debugging purposes
216
- - You need to limit the number of iteration attempts
217
-
218
- ### Basic Example
219
-
220
- ```ruby
221
- class RefactorPipeline < AgentC::Pipeline
222
- agent_review_loop(
223
- :refactor_code,
224
- max_tries: 5,
225
- implement: :initial_refactor,
226
- iterate: :improve_refactor,
227
- review: :code_review
228
- )
229
- end
230
- ```
231
-
232
- With i18n translations:
233
-
234
- ```yaml
235
- en:
236
- initial_refactor:
237
- prompt: "Refactor the code to improve readability"
238
- response_schema:
239
- code:
240
- description: "The refactored code"
241
-
242
- improve_refactor:
243
- prompt: |
244
- The previous refactor received this feedback:
245
- %{feedback}
246
-
247
- Please improve the refactor based on this feedback.
248
- response_schema:
249
- code:
250
- description: "The improved refactored code"
251
-
252
- code_review:
253
- prompt: |
254
- Review this code change:
255
- %{diff}
256
-
257
- Is it ready to merge?
258
- response_schema:
259
- approved:
260
- type: boolean
261
- description: "Whether the code is approved"
262
- feedback:
263
- type: string
264
- description: "Feedback if not approved (empty if approved)"
265
- ```
266
-
267
- ### How It Works
268
-
269
- The `agent_review_loop` executes in iterations:
270
-
271
- 1. **First iteration (try 0)**:
272
- - Runs all `implement` steps in order
273
- - If any implement step fails, the loop stops and marks the task as failed
274
- - Captures git diff of changes
275
- - Runs all `review` steps with the diff
276
- - Collects feedback from any reviewers who don't approve
277
-
278
- 2. **Subsequent iterations (try 1+)**:
279
- - Runs all `iterate` steps with accumulated feedback
280
- - If any iterate step fails, the loop stops and marks the task as failed
281
- - Captures git diff of changes
282
- - Runs all `review` steps with the new diff
283
- - Collects feedback from any reviewers who don't approve
284
-
285
- 3. **Loop continues until**:
286
- - All reviewers approve (feedback list is empty), OR
287
- - `max_tries` is reached, OR
288
- - Any step fails, OR
289
- - The task is marked as failed by other means
290
-
291
- ### Multiple Steps
292
-
293
- You can specify multiple steps for implement, iterate, and review:
294
-
295
- ```ruby
296
- agent_review_loop(
297
- :multi_file_refactor,
298
- max_tries: 5,
299
- implement: [
300
- :refactor_controller,
301
- :refactor_model,
302
- :refactor_view
303
- ],
304
- iterate: [
305
- :improve_controller,
306
- :improve_model,
307
- :improve_view
308
- ],
309
- review: [
310
- :code_quality_review,
311
- :security_review,
312
- :performance_review
313
- ]
314
- )
315
- ```
316
-
317
- Steps are executed in order. If any step fails, the loop stops immediately.
318
-
319
- ### Feedback Interpolation
320
-
321
- The `iterate` steps automatically receive a `%{feedback}` interpolation variable containing all feedback from reviewers, joined with `"\n---\n"` as a separator:
322
-
323
- ```yaml
324
- improve_refactor:
325
- prompt: |
326
- Previous feedback from reviewers:
327
- %{feedback}
328
-
329
- Please address all concerns.
330
- ```
331
-
332
- ### Review Schema
333
-
334
- Your "review" I18n should **not** include any response schema. AgentC will
335
- configure the schema for you.
336
-
337
- Review steps must return a response with these fields:
338
- - `approved` (boolean): Whether the work is approved
339
- - `feedback` (string): Feedback message if not approved (can be empty string if approved)
340
-
341
- If a review step fails to return valid data, the task is marked as failed.
342
-
343
- ### Optional: Recording Reviews
344
-
345
- If your record implements an `add_review` method, it will be called after each review iteration with the diff and collected feedback:
346
-
347
- ```ruby
348
- record(:my_record) do
349
- schema do |t|
350
- t.json(:reviews, default: [])
351
- end
352
-
353
- def add_review(diff:, feedbacks:)
354
- self.reviews ||= []
355
- self.reviews << {
356
- timestamp: Time.now.iso8601,
357
- diff: diff,
358
- feedbacks: feedbacks
359
- }
360
- save!
361
- end
362
- end
363
- ```
364
-
365
- This allows you to maintain a complete history of all review iterations.
366
-
367
- ### Default Iterate Behavior
368
-
369
- If you don't specify `iterate`, it defaults to the same value as `implement`:
370
-
371
- ```ruby
372
- # These are equivalent:
373
- agent_review_loop(:refactor, implement: :refactor_code, review: :review)
374
- agent_review_loop(:refactor, implement: :refactor_code, iterate: :refactor_code, review: :review)
375
- ```
376
-
377
- This is useful when the same prompt can handle both initial implementation and iteration based on feedback.
378
-
379
- ### Important Notes
380
-
381
- **Required parameters**: You must provide either `implement` or `iterate` (or both). Providing only `review` will raise an `ArgumentError`.
382
-
383
- **Max tries behavior**: When `max_tries` is reached, the loop completes the step successfully even if reviews haven't all approved. The loop doesn't fail the task when max tries is exceeded.
384
-
385
- **Git diff**: The git diff is captured after each iteration's implementation/iteration steps complete, and is passed to review steps via the `%{diff}` interpolation variable.
386
-
387
- **Failure handling**: If any implement, iterate, or review step returns invalid data or raises an exception, the entire agent_review_loop step is marked as failed and the task stops.
388
-
389
- **Step naming**: The `agent_review_loop` counts as a single pipeline step with the name you provide (e.g., `:refactor_code`), not separate steps for each iteration.
390
-
391
- ### Complete Example
392
-
393
- ```ruby
394
- class DocumentationPipeline < AgentC::Pipeline
395
- agent_review_loop(
396
- :write_documentation,
397
- max_tries: 3,
398
- implement: [:draft_readme, :draft_examples],
399
- iterate: [:improve_readme, :improve_examples],
400
- review: [:technical_review, :style_review]
401
- )
402
-
403
- step(:publish) do
404
- # Only reached if reviews passed or max_tries exceeded
405
- record.update!(published: true)
406
- end
407
- end
408
- ```
409
-
410
- With a record that tracks review history:
411
-
412
- ```ruby
413
- record(:documentation) do
414
- schema do |t|
415
- t.text(:readme_content)
416
- t.text(:examples_content)
417
- t.json(:review_history, default: [])
418
- t.boolean(:published, default: false)
419
- end
420
-
421
- def add_review(diff:, feedbacks:)
422
- self.review_history << {
423
- iteration: review_history.length + 1,
424
- timestamp: Time.now.iso8601,
425
- diff_size: diff.length,
426
- feedback_count: feedbacks.length,
427
- feedbacks: feedbacks
428
- }
429
- save!
430
- end
431
-
432
- def i18n_attributes
433
- attributes.merge(
434
- total_reviews: review_history.length,
435
- last_feedback: review_history.last&.dig("feedbacks")&.join("\n---\n") || "none"
436
- )
437
- end
438
- end
439
- ```
440
-
441
- ### When to Use agent_review_loop vs rewind_to!
442
-
443
- Use `agent_review_loop` when:
444
- - The review and iteration logic is straightforward and consistent
445
- - You want a declarative approach with less boilerplate
446
- - Multiple reviewers are involved
447
- - You want automatic feedback collection and interpolation
448
-
449
- Use `rewind_to!` when:
450
- - You need custom logic to determine whether to retry
451
- - The retry conditions are complex or context-dependent
452
- - You need to rewind to steps other than the immediate previous one
453
- - You want explicit control over the retry logic