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
The ARC Framework DSL is currently missing a proper way to formalize IO contracts between agents.
Currently the intended agent collaboration allows to dynamically call agent with a given context.
function(
name ="call_agent",
description ="Calls an Agent.",
params = types(string("name", "the name of the agent to call."))
) { (name) ->val currentConversation = get<Conversation>()
val result = callAgent(name.toString(), input = currentConversation).getOrNull()
// Extract just the content from the assistant's message or return an error message
result?.latest<AssistantMessage>()?.content ?:"Failed to call agent $name!"
}
Only the tools functions can use the parameter system to enforce input contracts.
While the filterInput and filterOuput can be used to fail an agent and trigger a retry the calling agent has no informations about the input parameters required by an agent.
I have been using a wrapper and Data classes, which allows the IO contract to be formalized quite easily with not too much boiler plate code. This allows to give two data classes on for the input and one for the output. Then the call wrapper converts these to JSON which is then passed to the called agent to for example be processed by the filterInput.
function(
name ="call-wikipedia-explorer",
description ="High-level Wikipedia search. Returns a JSON WikipediaSearchResponse.",
params = paramsFromDataClass<WikipediaExplorerRequest>()
) { args -> callAgentWrapper<WikipediaExplorerRequest, WikipediaExplorerResponse>("wikipedia-explorer", args) }
However when building medium to large scale mutli agent systems with orchestrators and intermediary LLM agents we can see the limitation of the current system.
The addition of a Tool-Agent system could really improve this workflow with the addition of strict IO contracts, automatic preprocessing of the input and output and direct formalized input data access from the agent $input.field.
This could be integrated to the current system quite well by just having tool-agent added to the tooling pool.
Annotated Data classes can be useful to specify the IO contract and give ranges to the different fields while still giving descriptions to the user.
@Serializable
@Doc("Input parameters for the Wikipedia Explorer agent.")
data classWikipediaExplorerRequest(
@Doc("User’s main query or topic.", example ="Charlemagne")
@Size(min =2, max =120)
valquery:String,
@Doc("Optional list of related subgoals to refine the search.", example ="['empire carolingien', 'sacre impérial']")
@Size(max =10)
valsubgoals:List<String>? = null,
@Doc("Language priority list (ISO 639-1 codes).", example ="['fr', 'en']", required =false)
vallangPriority:List<String>? = null,
)
and just be passed to an io block inside the agent
This would also require a change in the tool and agent registration, and maybe a dependance tree to build the correct tools and agents in the proper order.
I think this feature could really help in the idea of an open agentic network, which needs more formalized IO contracts to achieve more complexe agentic structures and better interoperability.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
The ARC Framework DSL is currently missing a proper way to formalize IO contracts between agents.
Currently the intended agent collaboration allows to dynamically call agent with a given context.
function( name = "call_agent", description = "Calls an Agent.", params = types(string("name", "the name of the agent to call.")) ) { (name) -> val currentConversation = get<Conversation>() val result = callAgent(name.toString(), input = currentConversation).getOrNull() // Extract just the content from the assistant's message or return an error message result?.latest<AssistantMessage>()?.content ?: "Failed to call agent $name!" }Only the tools functions can use the parameter system to enforce input contracts.
While the filterInput and filterOuput can be used to fail an agent and trigger a retry the calling agent has no informations about the input parameters required by an agent.
I have been using a wrapper and Data classes, which allows the IO contract to be formalized quite easily with not too much boiler plate code. This allows to give two data classes on for the input and one for the output. Then the call wrapper converts these to JSON which is then passed to the called agent to for example be processed by the filterInput.
function( name = "call-wikipedia-explorer", description = "High-level Wikipedia search. Returns a JSON WikipediaSearchResponse.", params = paramsFromDataClass<WikipediaExplorerRequest>() ) { args -> callAgentWrapper<WikipediaExplorerRequest, WikipediaExplorerResponse>("wikipedia-explorer", args) }However when building medium to large scale mutli agent systems with orchestrators and intermediary LLM agents we can see the limitation of the current system.
The addition of a Tool-Agent system could really improve this workflow with the addition of strict IO contracts, automatic preprocessing of the input and output and direct formalized input data access from the agent $input.field.
This could be integrated to the current system quite well by just having tool-agent added to the tooling pool.
#caller.agent.kts tools { +"wikipedia-explorer" +"wikipedia-summarizer" } #called.agent.kts isToolAgent = trueAnnotated Data classes can be useful to specify the IO contract and give ranges to the different fields while still giving descriptions to the user.
and just be passed to an io block inside the agent
io { input = InputDataClass output = OutputDataClass }This would also require a change in the tool and agent registration, and maybe a dependance tree to build the correct tools and agents in the proper order.
I think this feature could really help in the idea of an open agentic network, which needs more formalized IO contracts to achieve more complexe agentic structures and better interoperability.
Beta Was this translation helpful? Give feedback.
All reactions