Repository navigation
[Tech Debt][API][ReActAgent] Support skills in constructors - #1223
Conversation
|
|
||
| def resolveSkillNamesForSources(self, sources: list[dict]) -> list[str]: | ||
| """Resolve the names of Java-hosted skills declared by source specs.""" | ||
| return list(self._bridge.resolveSkillNamesForSources(sources) or []) |
There was a problem hiding this comment.
The actual bridge here is Java PythonResourceAdapterImpl, but resolveSkillNamesForSources() was added to JavaResourceAdapter. A Java agent using a Python model with constructor-provided Skills therefore raises AttributeError, confirmed through real Pemja. Could we add the missing delegation and test the actual bridge?
| merged.addAll(this.skills); | ||
| } | ||
| merged.addAll(resolved); | ||
| this.skills = new ArrayList<>(merged); |
There was a problem hiding this comment.
Could we synchronize the resolved skill names into both cross-language wrappers after the underlying model opens? PythonChatModelSetup.open() only delegates to Python, leaving the Java wrapper’s skills at its original descriptor value. With source-only configuration, getSkills() remains null, so Java ChatModelAction omits the skill directories from the bash call’s allowed_script_dirs, even after the bridge issue is fixed. The reverse wrapper has the same gap: Python JavaChatModelSetup.skills is not refreshed after Java open(). Copying the final list after each successful open() should address this. Please verify the resulting bash arguments in both directions.
| Map<String, Object> existing = this.resources.get(type); | ||
| // Rebuild to establish env-before-agent iteration order. | ||
| Map<String, Object> merged = new LinkedHashMap<>(envTyped); | ||
| merged.putAll(existing); |
There was a problem hiding this comment.
LinkedHashMap.putAll() replaces values without moving existing keys. With environment keys [z, a] and an agent override for z, the order becomes [agent-z, env-a], allowing environment skills to override agent skills. Could we remove overlapping keys before appending agent entries? The annotation-to-resource merge needs the same treatment.
| - The descriptor you pass in is not modified; the agent uses a copy with the combined skills. | ||
| - Only skill names are combined. The command policy of the built-in `bash` tool, such as `allowed_commands`, is always taken from the chat model descriptor, so set it there. | ||
|
|
||
| The skill sources must still be registered on the execution environment with `add_resource(..., ResourceType.SKILLS, ...)`. |
There was a problem hiding this comment.
Could we also document the Skills-object constructor with Java/Python examples? This section only describes skill-name lists and says sources must be registered on the environment, but passing a Skills object registers its sources on the agent automatically. Please distinguish the two forms and document how source-derived names combine with explicit descriptor skills, including the annotation → environment → agent precedence.
e0058c9 to
d5ca3f2
Compare
|
@wenjin272 good catch! Thank you for your review. I have fixed the four issues mentioned above:
|
wenjin272
left a comment
There was a problem hiding this comment.
Thanks for addressing my comments. LGTM. Could you rebase this PR onto the latest main and resolve the merge conflicts?
…ReActAgent constructors (apache#1193) - Java/Python ReActAgent: accept Skills object in constructor, register SkillSourceSpec marker via descriptor arguments, resolve at runtime through SkillManager.open(). - Agent-level skills override environment-level skills (layer-priority). - BaseChatModelSetup.open(): merge skills_sources from descriptor args. - ResourceContext: add resolveSkillNamesForSources() API. - SkillManager: maintain source-to-skills reverse index. - Agent: LinkedHashMap for insertion-order resource preservation. - AgentPlan: TreeMap-sorted skills before agent resources for correct priority. - 12 new tests across 4 files (api, plan, runtime, Python).
d5ca3f2 to
9e8a60d
Compare
Linked issue: #1193
Purpose of change
ReActAgentgains a fourth constructor parameter,skills, so skills can be named where the agent is builtinstead of on the chat model descriptor. Java overloads on
List<String>andSkills; Python takesSequence[str] | Skills | None. Passing nothing keeps today's behavior.Names go into a copy of the descriptor's
skills(descriptor's own first, constructor's appended, firstoccurrence kept). A
Skillsobject is registered as an agent-levelSKILLSresource plus askills_sourcesmarker;SkillManagerloads it at plan time andopen()resolves the marker into skillnames via
ResourceContext.resolveSkillNamesForSources, appending them after the explicit skills. A shareddescriptor is never mutated.
Behavioral Semantics
skills, or an emptySkills→ the descriptor's list is used as declared.bashcommand policy is untouched.Skills→ names resolved from its sources at runtime, added after the explicit skills.strfor PythonskillsraisesTypeError.@Skills/@skillsmethods merge first (Java by method name, Python by declaration order), thenenvironment, then agent resources; the later source wins a duplicate name.
nullfrom the bridge) yield no namesand no exception; only a marker element Jackson cannot convert raises.
Tests
ReActAgentTest(constructor form: overlay order, no-op on empty/None, descriptor notmutated, language preserved,
allowed_commandsuntouched),ReActAgentSkillsTest(theSKILLSresourceand its marker, resolved at runtime),
SkillManagerTest(source spec → skill names),BaseChatModelSetupSkillsTest(the marker survives anAgentPlanround trip),JavaResourceAdapterTest(bridge conversion and delegation),
AgentPlanDeclareSkillsTest(merge order, and aSKILLSresourcenamed the same at the environment and agent level keeping the agent's value).
test_react_agent.py(the same constructor contracts as the Java side),test_react_agent_skills.py(runtime resolution, merged with the explicit skills),test_cross_language_skill_sources.py(specs crossing the bridge as flat{scheme, params}maps).SkillsIntegrationTest(Java) andagent_skills_test.py(Python) now name the skill on theReActAgentconstructor instead of the descriptorAPI
ReActAgent— Java: new 4-arg constructors overList<String>/Skills, the 3-arg form unchanged (abare
nullfourth argument is now ambiguous and needs a cast). Python: newskills=Nonekeyword.ResourceContext/JavaResourceAdapter/SkillManager/AgentPlan— new methods; nothing existingbreaks.
Agent.addResourcesIfAbsent— environment entries now come first in iteration order, and a same-nameclash keeps the agent's value, matching the Javadoc.
Documentation
doc-neededdoc-not-neededdoc-includedWas this patch authored or co-authored using generative AI tooling?
Generated-by: cursor (deepseek-v4.1-flash)