composable_agents 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 72f4795399719375c8c55c7efea5b4e0ddb18918b1d72473040d39cd2c1b7ecd
4
+ data.tar.gz: a70a660e7ee3ad362976336b8bf75abac96e931f36bfcdca7cf755853326090a
5
+ SHA512:
6
+ metadata.gz: af2e51d1e5e4f10641e162f081d2daee958cc6571f35f60ea7266eb04470a2d3894a8b5bfc0744d5f0077b010bb43e76a61556823e2edcdf920c578f8b7b915c
7
+ data.tar.gz: f63f287abc216032f4abc77b0c60906b59e0cd21fee222b3dfc606d96fc760c09d24d8b56f94ccf5660b6b953e7e06b3edf2171fadea1ed278dcd5a226f897db
data/CHANGELOG.md ADDED
@@ -0,0 +1,109 @@
1
+ # [v0.0.1](https://github.com/Muriel-Salvan/composable_agents/compare/...v0.0.1) (2026-07-01 15:49:59)
2
+
3
+ ### Patches
4
+
5
+ * [test: make JSON parse error assertions OS-independent](https://github.com/Muriel-Salvan/composable_agents/commit/218e681fac7a30c38a696ea8c27927932c7d74ed)
6
+ * [fix: handle missing global config when loading skills](https://github.com/Muriel-Salvan/composable_agents/commit/e33ea43413cdc9b8ade3155041a2e5e390d1b5b1)
7
+ * [docs: add YARD group markers for public/internal API](https://github.com/Muriel-Salvan/composable_agents/commit/2034b866895cd1843b3a758d2ca922331bb5ef76)
8
+ * [ci: integrate Codecov coverage and fix YARD documentation](https://github.com/Muriel-Salvan/composable_agents/commit/d623ed40557ba6803f7b3d12c8c57ac1174a79f8)
9
+ * [refactor: replace `.to_json` with `JSON.dump` for explicit serialization](https://github.com/Muriel-Salvan/composable_agents/commit/04eef9a9ac5a9493704c0e835ddcb4ecf301ad1b)
10
+ * [docs: add TODO comments about skillkit and AGENTS.md generation](https://github.com/Muriel-Salvan/composable_agents/commit/e08db4b87a2d2ad0f080de5323704fa4385ddae6)
11
+ * [fix(cline): gracefully handle missing global or project configs in skill lookup](https://github.com/Muriel-Salvan/composable_agents/commit/4744cdd8a353edfd3bc42702c37a740fcc0580e0)
12
+ * [fix(agent): avoid NoMethodError when error lacks response](https://github.com/Muriel-Salvan/composable_agents/commit/d71fdbd5b67daa4d68b048e733a7525ac995dd52)
13
+ * [refactor: introduce full_name for better agent identification](https://github.com/Muriel-Salvan/composable_agents/commit/077f4948fdfcc602286be58c1741e6ae40aeff19)
14
+ * [feat(agent): add full_name method for better identification in logs](https://github.com/Muriel-Salvan/composable_agents/commit/d0194932263b4a38a0c23aac6c3091abf583819a)
15
+ * [fix(resumable): deep clone agent_state to avoid unintended state mutation](https://github.com/Muriel-Salvan/composable_agents/commit/567c96ec60a1d67d7126d67721c8abddca62ab96)
16
+ * [feat(agents): add deep_transform_keys for consistent state serialization](https://github.com/Muriel-Salvan/composable_agents/commit/85d1247b1bd227d03ffa8055248ae394f5159515)
17
+ * [refactor: Use a better interface with cline-rb to update configs](https://github.com/Muriel-Salvan/composable_agents/commit/478115d0635d1400b7a888cefd3924ad61bb9054)
18
+ * [feat(resumable): support extra input artifacts in step definitions](https://github.com/Muriel-Salvan/composable_agents/commit/fd272452d23440e71aa1a2c11b3c4180302764bf)
19
+ * [feat(prompt_driven_agent): add attr_accessors for agent configuration parameters](https://github.com/Muriel-Salvan/composable_agents/commit/ce6b0d30a52e642f0eb8a5ab585e071fca754ca3)
20
+ * [refactor: simplify instructions handling by centralizing Instructions.new](https://github.com/Muriel-Salvan/composable_agents/commit/99ed0a25288fec0992488fe1109ef8a253ec71bf)
21
+ * [refactor: replace `assistant_artifact_name` with instance method `artifact_ref`](https://github.com/Muriel-Salvan/composable_agents/commit/3f3931074364cf32db7a68ad07cad5f5b568edfb)
22
+ * [fix(cline): exclude context from first prompt and stored conversation history](https://github.com/Muriel-Salvan/composable_agents/commit/6e229c2733128df64b8ce867dcb19a7f86bfd04c)
23
+ * [refactor: move context injection from MarkdownHeavy to Cline agent](https://github.com/Muriel-Salvan/composable_agents/commit/6b12345374de5c22bf384414683c1aeafc9f0069)
24
+ * [fix(cline): use JSON.dump for context serialization to prevent angle bracket escaping](https://github.com/Muriel-Salvan/composable_agents/commit/31f5181d2c6d9712f752122f33c1d2c70ec9c2a3)
25
+ * [refactor: Move and enhance parse_output_artifacts to MarkdownHeavy with type-based parsing](https://github.com/Muriel-Salvan/composable_agents/commit/14959ebf93f03edb62816176e404a2fe1fd8fe82)
26
+ * [test(markdown-heavy): add missing output artifact type template specs](https://github.com/Muriel-Salvan/composable_agents/commit/6aacfdf270de6f0194eb689a8e778a531e2befe2)
27
+ * [refactor: extract example_json_block method for artifact examples](https://github.com/Muriel-Salvan/composable_agents/commit/7f57ac2a89e6d07446025cada1650e70eb24bdce)
28
+ * [feat: enhance output artifact instructions with structured sections](https://github.com/Muriel-Salvan/composable_agents/commit/6f8d1e1f83491609dd5d630d72eb84d4f5328cb7)
29
+ * [feat(artifact_contract): add artifact type validation](https://github.com/Muriel-Salvan/composable_agents/commit/3ff741000a7687e52c71517c0227d893fc140b99)
30
+ * [fix(cline): handle nested code blocks in artifact parsing](https://github.com/Muriel-Salvan/composable_agents/commit/39002dd15ab01dc7d2b8a0f173fcb4c465f36285)
31
+ * [fix: delete previous output artifact when reporting error for same artifact](https://github.com/Muriel-Salvan/composable_agents/commit/39fb0d214340e9cf48d5f4cfbb4017838623d4b2)
32
+ * [test: reorganize agent constructor parameter specs into new file](https://github.com/Muriel-Salvan/composable_agents/commit/c931d45901843001673a303a8ae78c04d9325031)
33
+ * [test: document non-deterministic failure in output artifacts retry test](https://github.com/Muriel-Salvan/composable_agents/commit/6a8359b7275d30c25967ab331e11294bd93b75d2)
34
+ * [feat: report errors for output artifacts to agent for resolution](https://github.com/Muriel-Salvan/composable_agents/commit/8d88819d576cd665adae8e9966c3f4770f969f4e)
35
+ * [fix(cline/agent): guard against nil artifact content after JSON parse failure](https://github.com/Muriel-Salvan/composable_agents/commit/0b22d96a140c213ffdba96d64dc560b97023e2a0)
36
+ * [fix: align Markdown headers in user instructions to level 2 for consistent hierarchy](https://github.com/Muriel-Salvan/composable_agents/commit/becefec461883edbc06c6fc64402b893db8d2fcd)
37
+ * [refactor(agent): Harmonize and simplify prompt rendering](https://github.com/Muriel-Salvan/composable_agents/commit/430cdc3ab86baa878cafde9c8ddbe55010e16c28)
38
+ * [refactor!: rename user_message to user_instructions, and make it renderable, like system instructions](https://github.com/Muriel-Salvan/composable_agents/commit/3e09a02987ebd4f463e91678fdad9d2bfe46f47a)
39
+ * [feat(instructions): add Instructions class and refactor agent to use it](https://github.com/Muriel-Salvan/composable_agents/commit/e0c709eb6a699c9766df34f31f6529de5777403d)
40
+ * [refactor: rename `instructions` to `system_instructions` for clarity](https://github.com/Muriel-Salvan/composable_agents/commit/021f2a63db6b02e97a4c2ddbd608ba4831773b83)
41
+ * [refactor: make prompt attributes optional and consolidate name default](https://github.com/Muriel-Salvan/composable_agents/commit/83ddad2c91f9b3322b296acd136efb89faac02e0)
42
+ * [fix: add exception message to JSON parse error log for artifacts](https://github.com/Muriel-Salvan/composable_agents/commit/220eb56d59734597db8205762e7ed693dba4f710)
43
+ * [refactor(cline): extract output artifact parsing into dedicated method and add on_message callback](https://github.com/Muriel-Salvan/composable_agents/commit/5ea6a31e5ecbaa6cdb5348747512908dfc4999e2)
44
+ * [feat: distinguish input and output artifacts in JSON blocks](https://github.com/Muriel-Salvan/composable_agents/commit/72b64c357a7c904c79ee242ea5c1641c3369d123)
45
+ * [feat(cline): add configure_global parameter to customize global settings](https://github.com/Muriel-Salvan/composable_agents/commit/61ba373ea5ea080855da67c58bc5fb97bfe4931c)
46
+ * [refactor: rename configure parameter to configure_provider in Cline::Agent](https://github.com/Muriel-Salvan/composable_agents/commit/80c1d5b5df53d659bef98aaf728be36e26da3956)
47
+ * [test: add context rendering strategy and agent context spec](https://github.com/Muriel-Salvan/composable_agents/commit/28a57bc10bf7df3ad39935b84169f49077eb18d7)
48
+ * [refactor(test): extract CLINE_API_KEY clearing helper and remove redundant cleanup](https://github.com/Muriel-Salvan/composable_agents/commit/730aa7127db580ec6b4812374cd616c1f677b60a)
49
+ * [refactor(tests): move .composable_agents_test cleanup to spec_helper](https://github.com/Muriel-Salvan/composable_agents/commit/0a527ff1f71fc3498344048fe1b506d201729cb5)
50
+ * [feat(prompt_driven_agent): accept non-string messages and convert via to_hash](https://github.com/Muriel-Salvan/composable_agents/commit/d1bd22c9a53eb90bb699711588c982a8e5298d4d)
51
+ * [feat: enhance skill management with dependency resolution and remove plan_mode](https://github.com/Muriel-Salvan/composable_agents/commit/6d7813992009ef0615aa825abef9456a1a6844d4)
52
+ * [feat: add Cline agent support and update project configurations](https://github.com/Muriel-Salvan/composable_agents/commit/f05f4ac5c5bf729b15603ee117008180e15c25bf)
53
+ * [feat(test): add debug helpers and enhance conversation expectation with regex support](https://github.com/Muriel-Salvan/composable_agents/commit/acfff56258dade966a4c5892c7043e94f53b2a10)
54
+ * [test: remove render_calls tracking from TestRenderingStrategy](https://github.com/Muriel-Salvan/composable_agents/commit/c80e1ba615465b4fb9579cfb5c99af1794147c3c)
55
+ * [test(composable_agents): add contracts option to prompt-driven agent shared examples](https://github.com/Muriel-Salvan/composable_agents/commit/34b4dea480e38f164de8a4ebd71463807839328e)
56
+ * [refactor: Split AiAgents tests between generic prompt-driven-agent shared examples and AiAgents specific ones](https://github.com/Muriel-Salvan/composable_agents/commit/b8009db09ad15fa8d861769fe713078c9f9175ae)
57
+ * [refactor(artifact_contract): rename constructor parameters to `*_contracts`](https://github.com/Muriel-Salvan/composable_agents/commit/64f1b47a00a9c58768e0e3dd5ccc5c0b2a3cfff8)
58
+ * [test(prompt_rendering): split specs for Markdown & MarkdownHeavy](https://github.com/Muriel-Salvan/composable_agents/commit/1d7d2a2be7eda472642210ffcffc853b446e569a)
59
+ * [feat: add MarkdownHeavy prompt rendering strategy for complex agents](https://github.com/Muriel-Salvan/composable_agents/commit/7131502bdeee810bd155bb2e4bfa7e326f8274fb)
60
+ * [fix: unescape dots in headers when converting to CommonMark](https://github.com/Muriel-Salvan/composable_agents/commit/396809b5698d06dd4841eab1a38f70d4a352bc1e)
61
+ * [fix: restrict debug mode to explicit '1' environment variable](https://github.com/Muriel-Salvan/composable_agents/commit/ae23f136d1dde83e46cf9d4f1e388dc79dbb6080)
62
+ * [feat(prompt_driven_agent): normalize output artifact contracts and propagate input artifacts](https://github.com/Muriel-Salvan/composable_agents/commit/5bc3b650d2ebff5d974425618dc3018173c30567)
63
+ * [feat: Add AiAgentUserInteraction mixin with tool-based user interaction](https://github.com/Muriel-Salvan/composable_agents/commit/72f08098e5d73c046ddc268ddb28fad12b8fef2f)
64
+ * [feat(examples): add examples](https://github.com/Muriel-Salvan/composable_agents/commit/62ff39a63449c0f4efaa3e59b84354289ec977a8)
65
+ * [refactor: Store conversation in agent state, not output artifact](https://github.com/Muriel-Salvan/composable_agents/commit/08e15c13492f1f75992fee09483f3c4048ac6691)
66
+ * [chore(log): clarify resumable step debug log by adding artifacts descriptor](https://github.com/Muriel-Salvan/composable_agents/commit/2dbc662f65b8e1b6400a48afd2ad825bbf914ec9)
67
+ * [feat: store conversation timestamps as native Time objects instead of strings](https://github.com/Muriel-Salvan/composable_agents/commit/45752d1f21aa9ab61825b11227b82b1227304794)
68
+ * [refactor(interaction): Extract user question handling from tool to agent mixin](https://github.com/Muriel-Salvan/composable_agents/commit/d70c455358cee48318ec855bfd04c61780aca926)
69
+ * [test: Add complete spec coverage for CreateArtifactTool class](https://github.com/Muriel-Salvan/composable_agents/commit/4899ec637c30d48145e66a4fd7a43bcee9abbcd0)
70
+ * [test: Add comprehensive test specs for GetArtifactTool functionality](https://github.com/Muriel-Salvan/composable_agents/commit/9129f5d41ed8a678ac9c37095d9c78c1b3cc8c8b)
71
+ * [feat(agents): Add AskUserTool, UserInteraction mixin and extendable tools hook](https://github.com/Muriel-Salvan/composable_agents/commit/7b06cd66567b3fb72ce70544dbbedeb49733f378)
72
+ * [fix(tools): Update CreateArtifactTool description to prevent unprompted artifacts](https://github.com/Muriel-Salvan/composable_agents/commit/93affd907e2a8dc9d0d875bcbd77d2983284d65e)
73
+ * [feat: Add configurable message author & fix incorrect prompt attribution](https://github.com/Muriel-Salvan/composable_agents/commit/21bef7be8e958097b0a6792c52bdcd0c8196c546)
74
+ * [feat(agents): Implement complete state persistence preserving context & conversation history](https://github.com/Muriel-Salvan/composable_agents/commit/1b2244acfe02db55514ed8d9ef04cc225e206560)
75
+ * [feat: Extend artifact contracts with optional flags and normalization logic](https://github.com/Muriel-Salvan/composable_agents/commit/f67da2ba9e435fdef7f0d3c846a274de2dcc2eb4)
76
+ * [refactor: extract markdown header logic to shared Utils::Markdown utility module](https://github.com/Muriel-Salvan/composable_agents/commit/99b21f165cd10538300cc7087be57a53fe3ac417)
77
+ * [feat(agent): Add raw API response body to error messages for improved debugging](https://github.com/Muriel-Salvan/composable_agents/commit/7ca9574299d243fae78e84533141f93f9f86099f)
78
+ * [feat: Add automatic conversation history tracking for PromptDrivenAgent](https://github.com/Muriel-Salvan/composable_agents/commit/75f76611186c3977e968d747065360572dfb766d)
79
+ * [refactor: Standardize missing artifact prompt flow, add infinite loop detection TODO](https://github.com/Muriel-Salvan/composable_agents/commit/516bed36c6582712981766e5134a35bc188e273a)
80
+ * [feat(artifact_contract): Add constructor params to declare artifacts on initialization](https://github.com/Muriel-Salvan/composable_agents/commit/ab185f321204381fae6bcf37f48ea24852c8cb0b)
81
+ * [feat!: Update Agent run signature to accept input artifacts as kwargs](https://github.com/Muriel-Salvan/composable_agents/commit/ce5a75d4e8649fb78992dec5ac2adb4bb49e7cd4)
82
+ * [refactor(artifact_contract): Replace constructor initialisation with explicit contract methods](https://github.com/Muriel-Salvan/composable_agents/commit/4075f2e4ad81fa7102b9eaaa0cbd7e0c93ce0842)
83
+ * [feat: add public model attribute reader to Agent class with test coverage](https://github.com/Muriel-Salvan/composable_agents/commit/54a0545bcf386ee1bcd4c41eae2509c45bec3c57)
84
+ * [feat: add markdown header normalization for agent prompt rendering](https://github.com/Muriel-Salvan/composable_agents/commit/cb29d54308891496fc710fe05dfba223ec099d67)
85
+ * [fix: sanitize step names to produce valid JSON state filenames](https://github.com/Muriel-Salvan/composable_agents/commit/284fd44dfbe45cdd47930620fc99f56b7ced5de1)
86
+ * [feat: Add agent state export/import persistence using Marshal serialization](https://github.com/Muriel-Salvan/composable_agents/commit/aebfafbfdc055cbd6467b7078c76be2a5664ce52)
87
+ * [fix(ai_agents): Initialize agent context in constructor to preserve across runs](https://github.com/Muriel-Salvan/composable_agents/commit/79cf76961bc0fcbd8e6eba25a5537e6e35d745b6)
88
+ * [refactor: Remove explicit user_message run param, source from input_artifacts](https://github.com/Muriel-Salvan/composable_agents/commit/9c9cf1254e6d44a9554438aadc5fa3fee1ac4d20)
89
+ * [feat(resumable): Add sub-agent step support, update RuboCop configuration](https://github.com/Muriel-Salvan/composable_agents/commit/720e540efcc529efdbd286287db7b49ef0b9674c)
90
+ * [feat(resumable): Add step_agent helper to run agents as resumable workflow steps](https://github.com/Muriel-Salvan/composable_agents/commit/50233e052b461eab6311e0f5980a9494be59c70b)
91
+ * [docs: Standardize agent execution method documentation across all implementations](https://github.com/Muriel-Salvan/composable_agents/commit/48a888392d400e49b4ed9ff98ca000fe14d89e68)
92
+ * [refactor(artifact_contract): migrate from class to instance level artifact definitions](https://github.com/Muriel-Salvan/composable_agents/commit/9f49be96633c6dcbc4e7bbed5fe69a3801e300d7)
93
+ * [test: Add comprehensive spec suite for Markdown prompt rendering strategy](https://github.com/Muriel-Salvan/composable_agents/commit/59feccbca02a901961f5918762e7874c4de4aaf4)
94
+ * [test(agent_spec): add error propagation test & configurable mock run results](https://github.com/Muriel-Salvan/composable_agents/commit/71c92bdf7bc470c24ef1fd53d0dbd824595c3595)
95
+ * [feat: Add AiAgents Agent base implementation, update dependencies & Rubocop](https://github.com/Muriel-Salvan/composable_agents/commit/6f1eb5f7aa6102040747e81513287395644d93a8)
96
+ * [feat(agent): Add optional agent name attribute and logging context](https://github.com/Muriel-Salvan/composable_agents/commit/65e2f6e8313825a1f0714653c249c5060ea57a52)
97
+ * [feat: Add Zeitwerk autoloading and remove manual require boilerplate](https://github.com/Muriel-Salvan/composable_agents/commit/78136fb9bb59777952e811237783a25aca988832)
98
+ * [refactor: Extract agent logging logic into reusable Logger mixin](https://github.com/Muriel-Salvan/composable_agents/commit/1dba2d9b32e007ec8c6d7c024943166dfc2d38f2)
99
+ * [fix(artifact_contract): filter undeclared input artifacts before passing to super run](https://github.com/Muriel-Salvan/composable_agents/commit/b7672c6602c47b56f25ae25b6355acf2a5da2d77)
100
+ * [fix(artifact_contract): merge artifacts instead of replacing, add inheritance tests](https://github.com/Muriel-Salvan/composable_agents/commit/934a1370dd67b457882bdb757f4b4dfe9cb93aba)
101
+ * [test(resumable): Refactor Resumable mixin spec setup & helper methods](https://github.com/Muriel-Salvan/composable_agents/commit/ea05a4a42bcc5a09c5b06f37be54f50d910f3106)
102
+ * [refactor(agent): extract artifact contract logic from base Agent class](https://github.com/Muriel-Salvan/composable_agents/commit/105af8b7ac013c7d55adae2be802e814116252d5)
103
+ * [fix(resumable): Fix persisted step key symbolization, add resume scenario tests](https://github.com/Muriel-Salvan/composable_agents/commit/aa1c6ebf78709b10df48ae083f52c87fcdfca7f5)
104
+ * [feat(agent): Implement base logging capability with configurable debug mode](https://github.com/Muriel-Salvan/composable_agents/commit/d2fd1f0c9739622af7dc790b38a4a4e5adf4e8f1)
105
+ * [feat: Add resumable agent mixin, base constructor and project configs](https://github.com/Muriel-Salvan/composable_agents/commit/24a23b6851a1e534f272b388e0437337a3d835dc)
106
+ * [feat(core): Fix artifact accessor methods, correct super call, add RubyAgent specs](https://github.com/Muriel-Salvan/composable_agents/commit/320e8ab1c32ecbcd2094bafe149ba8a50c63bdda)
107
+ * [feat: Add base Agent abstract class and initial RubyAgent implementation](https://github.com/Muriel-Salvan/composable_agents/commit/8ab928f4a0525b7fc2a33b25c1e7e7f162291250)
108
+ * [chore: Setup RuboCop linting, add code quality specs & clean project code](https://github.com/Muriel-Salvan/composable_agents/commit/a7c46f52148d7971c3b793bf7f124c890c9ee9b9)
109
+ * [test: Move gem packaging validation from CI workflow to dedicated RSpec spec](https://github.com/Muriel-Salvan/composable_agents/commit/06c58a9928c9a373d92ff9e6b7ba8251b70855ff)
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # composable_agents
2
+
3
+ Composable AI agents framework.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add composable_agents
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install composable_agents
14
+
15
+ ## Usage
16
+
17
+ TODO: Write usage instructions here
18
+
19
+ ## Development
20
+
21
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rspec` to run the tests.
22
+
23
+ ## Contributing
24
+
25
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Muriel-Salvan/composable_agents.
26
+
27
+ ## License
28
+
29
+ The gem is available as open source under the terms of the [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause).
data/TODO.md ADDED
@@ -0,0 +1,5 @@
1
+ * README.rb.
2
+ * Check Rubocop-rspec exceptions and try to remove them.
3
+ * Add agents manifesto for contributors.
4
+ * Add some info logging (not debug) that would allow detecting when infinite loops or blocked agents occur.
5
+ * Make tests run faster.
@@ -0,0 +1,53 @@
1
+ module ComposableAgents
2
+ # Abstract computational unit that transforms inputs into outputs.
3
+ # Agents may internally use LLMs, tools, or other agents.
4
+ # Agents are stateless: they take input artifacts and return output artifacts.
5
+ class Agent
6
+ include Mixins::Logger
7
+
8
+ # @!group Public API
9
+
10
+ # @return [String, nil] The agent name, if any
11
+ attr_reader :name
12
+
13
+ # Constructor
14
+ #
15
+ # @param name [String, nil] Agent name, or nil if none
16
+ # @param composable_agents_dir [String] Base directory where composable agents can store data
17
+ def initialize(
18
+ name: nil,
19
+ composable_agents_dir: '.composable_agents'
20
+ )
21
+ @name = name
22
+ @composable_agents_dir = composable_agents_dir
23
+ end
24
+
25
+ # Return the full name of the agent.
26
+ # This method is intended to be overridden by subclasses to give better full names, tailored to the kind of agent.
27
+ # The full name can be used in logs and traces to better identify the agent.
28
+ #
29
+ # @return [String] The agent's full name
30
+ def full_name
31
+ "#{name || 'Unnamed'}#{" (#{self.class.name.split('::').last})" if self.class != Agent && self.class.name}"
32
+ end
33
+
34
+ # @!group Internal
35
+
36
+ # Execute the agent to generate some output artifacts based on some input artifacts.
37
+ #
38
+ # @param input_artifacts [Hash{Symbol => Object}] The input artifacts content
39
+ # @return [Hash{Symbol => Object}] Output artifacts content
40
+ def run(**input_artifacts)
41
+ raise NotImplementedError, 'This method should be implemented by an Agent subclass'
42
+ end
43
+
44
+ private
45
+
46
+ # Fields to be logged
47
+ #
48
+ # @return [Array<String>] Fields to log
49
+ def log_fields
50
+ [full_name]
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,105 @@
1
+ require 'base64'
2
+ require 'agents'
3
+
4
+ module ComposableAgents
5
+ # All agents from this module work with the awesome ai-agents Rubygem
6
+ module AiAgents
7
+ # Agent implementation that uses an ai-agent's AgentRunner.
8
+ class Agent < PromptDrivenAgent
9
+ # @!group Public API
10
+
11
+ # Initialize a new agent with a list of ai-agents' Agents to be used with an AgentRunner
12
+ #
13
+ # @param model [String] Model to be used
14
+ # @param params [Hash{Symbol => Object}] Additional parameters to give to the ai-agents' agent
15
+ # @param handoff_agents [Array<Agents::Agent>] The list of additional agents that can be used for handoffs.
16
+ def initialize(
17
+ *args,
18
+ model: Agents.configuration.default_model,
19
+ params: {},
20
+ handoff_agents: [],
21
+ **kwargs
22
+ )
23
+ super(*args, **kwargs)
24
+ @model = model
25
+ @params = params
26
+ @handoff_agents = handoff_agents
27
+ @context = {}
28
+ end
29
+
30
+ # Return the full name of the agent.
31
+ # This method is intended to be overridden by subclasses to give better full names, tailored to the kind of agent.
32
+ # The full name can be used in logs and traces to better identify the agent.
33
+ #
34
+ # @return [String] The agent's full name
35
+ def full_name
36
+ "#{name || 'Unnamed'} (AiAgent #{@model})"
37
+ end
38
+
39
+ # @!group Internal
40
+
41
+ # Export the agent state for persistence
42
+ #
43
+ # @return [Object] Serialized state that can be marshalled to JSON
44
+ def export_state
45
+ super.merge(deep_transform_keys(context: Base64.encode64(Marshal.dump(@context)), &:to_s))
46
+ end
47
+
48
+ # Import the agent state from persistence
49
+ #
50
+ # @param state [Object] Serialized state
51
+ def import_state(state)
52
+ super
53
+ @context = Marshal.load(Base64.decode64(deep_transform_keys(state, &:to_sym)[:context]))
54
+ end
55
+
56
+ private
57
+
58
+ # Get the agent runner.
59
+ # Memoize it.
60
+ #
61
+ # @return [Agents::AgentRunner] The agent runner to be used
62
+ def agent_runner
63
+ @agent_runner ||= Agents::AgentRunner.new(
64
+ [
65
+ Agents::Agent.new(
66
+ model: @model,
67
+ name:,
68
+ params: @params,
69
+ instructions: @system_prompt,
70
+ tools: [
71
+ Tools::CreateArtifactTool.new(self),
72
+ Tools::GetArtifactTool.new(@input_artifacts)
73
+ ] + agent_tools
74
+ )
75
+ ] + @handoff_agents
76
+ )
77
+ end
78
+
79
+ # Process a user prompt.
80
+ #
81
+ # @param user_prompt [String] The rendered user prompt
82
+ # @return [String] The output of the prompt
83
+ def prompt(user_prompt)
84
+ result = agent_runner.run(user_prompt, context: @context)
85
+ unless result.error.nil?
86
+ raise <<~EO_ERROR.strip
87
+ Error: #{result.error.detailed_message}
88
+ #{result.error.backtrace.join("\n")}
89
+ #{result.error.response.response_body if result.error.respond_to?(:response)}
90
+ EO_ERROR
91
+ end
92
+
93
+ @context = result.context
94
+ result.output
95
+ end
96
+
97
+ # Returns the list of tools available for this agent
98
+ #
99
+ # @return [Array<Agents::Tool>] List of tools
100
+ def agent_tools
101
+ []
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,38 @@
1
+ module ComposableAgents
2
+ module AiAgents
3
+ # Collection of tools that can be used with ai-agents' agents
4
+ module Tools
5
+ # Tool that is used to ask the user for some input
6
+ class AskUserTool < Agents::Tool
7
+ # @!group Internal
8
+
9
+ include Mixins::Logger
10
+
11
+ description <<~EO_DESCRIPTION
12
+ Ask the user a question and wait for their response.
13
+ If you need information from the user, call this tool instead of asking directly.
14
+ Do not guess user input.
15
+ EO_DESCRIPTION
16
+ param :question, type: 'string', desc: 'Question to be asked to the user'
17
+
18
+ # Constructor
19
+ #
20
+ # @param agent [Agent] The agent that is using this tool
21
+ def initialize(agent)
22
+ super()
23
+ @agent = agent
24
+ end
25
+
26
+ # Perform the tool's action.
27
+ # This is called by ai-agents when the model requires it.
28
+ #
29
+ # @param _tool_context [Agents::ToolContext] The tool context
30
+ # @param question [String] The question asked
31
+ # @return [String] The tool's response
32
+ def perform(_tool_context, question:)
33
+ @agent.ask(question)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ module ComposableAgents
2
+ module AiAgents
3
+ module Tools
4
+ # Tool that is used to create a new artifact's content
5
+ class CreateArtifactTool < Agents::Tool
6
+ # @!group Internal
7
+
8
+ include Mixins::Logger
9
+
10
+ description <<~EO_DESCRIPTION
11
+ Create an output artifact.
12
+ Only create artifacts when the user is asking you to create an artifact named `{name}`.
13
+ Do not create artifacts unless the user is asking you to.
14
+ EO_DESCRIPTION
15
+ param :name, type: 'string', desc: 'Artifact name'
16
+ param :content, type: 'string', desc: 'Artifact content'
17
+
18
+ # Constructor
19
+ #
20
+ # @param agent [PromptDrivenAgent] The agent that will receive output artifacts
21
+ def initialize(agent)
22
+ super()
23
+ @agent = agent
24
+ end
25
+
26
+ # Perform the tool's action.
27
+ # This is called by ai-agents when the model requires it.
28
+ #
29
+ # @param _tool_context [Agents::ToolContext] The tool context
30
+ # @param name [String] The required artifact's name
31
+ # @param content [String] The required artifact's content
32
+ # @return [String] The tool's response
33
+ def perform(_tool_context, name:, content:)
34
+ @agent.save_output_artifact(name.to_sym, content)
35
+ "Artifact `#{name}` created successfully."
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,39 @@
1
+ module ComposableAgents
2
+ module AiAgents
3
+ module Tools
4
+ # Tool that is used to read an artifact's content
5
+ class GetArtifactTool < Agents::Tool
6
+ # @!group Internal
7
+
8
+ include Mixins::Logger
9
+
10
+ description 'Get an input artifact'
11
+ param :name, type: 'string', desc: 'Artifact name'
12
+
13
+ # Constructor
14
+ #
15
+ # @param artifacts [Hash{Symbol => Object}>] The artifacts store
16
+ def initialize(artifacts)
17
+ super()
18
+ @artifacts = artifacts
19
+ end
20
+
21
+ # Perform the tool's action.
22
+ # This is called by ai-agents when the model requires it.
23
+ #
24
+ # @param _tool_context [Agents::ToolContext] The tool context
25
+ # @param name [String] The required artifact's name
26
+ # @return [String] The tool's response
27
+ def perform(_tool_context, name:)
28
+ name_sym = name.to_sym
29
+ if @artifacts.key?(name_sym)
30
+ log_debug "Artifact `#{name}` read successfully."
31
+ @artifacts[name_sym].to_s.strip
32
+ else
33
+ "[ERROR] No artifact named #{name}, don't call this tool with the name #{name} anymore."
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end