Skip to content

[Tech Debt][API][ReActAgent] Support Skills directly in Java and Python constructors #1193

Closed

Description

@wenjin272

Search before asking

  • I searched existing issues for duplicates; related work is linked below where applicable.

Description

This is a child issue of #1055.

Problem

ReActAgent constructors accept a chat-model descriptor, prompt, and output schema, but do not expose Skills as a first-class constructor option. Users have to know the chat-model descriptor configuration to attach Skills to the built-in agent.

Proposed direction

Add equivalent Java/Python skills constructor support. Agree whether the argument accepts registered resource names, resource declarations, or both, and document how those resources become available to the agent.

Define how constructor Skills interact with Skills already configured on the chat-model descriptor: merge/override behavior, ordering, duplicate/conflicting declarations, and whether the supplied descriptor is copied or modified. Clarify ownership and precedence of allowed_commands so the new convenience API does not silently change command permissions.

Acceptance criteria

  • Java/Python expose equivalent Skills configuration on ReActAgent.
  • Constructor and descriptor settings have deterministic, documented combination rules.
  • Tests cover constructor-only, descriptor-only, combined/conflicting declarations, and command-policy behavior, including actual Skill availability in the ReAct execution path.
  • Examples and applicable YAML-facing semantics remain consistent with the resource model.

Relevant code: api/.../agents/ReActAgent.java, python/flink_agents/api/agents/react_agent.py.

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Activity

  1. added
    tech debt[Issue Type] User-unaware issues, such as code refactor and infrastructure maintenance.
    priority/majorDefault priority of the PR or issue.
    on Oct 3, 2026
  2. da-daken commented on Oct 8, 2026

    @da-daken
    Contributor

    hi @wenjin272 If no one has taken this on yet, I'd be happy to finish it.

    Regarding adding skills via constructor parameters, there are two entry points for adding skills, so both may be configured at the same time. Here is my proposed approach:

    • Merge the skills from the constructor parameters with the skills from the descriptor.

    • If they have the same name, just deduplicate them.

    • For ordering, the descriptor skills can come first, and the constructor-parameter skills can be appended as a supplement.

    All of the above rules will be clearly documented in comments and documentation. WDYT

  3. wenjin272 commented on Oct 8, 2026

    @wenjin272
    ContributorAuthor

    Thanks for picking this up @da-daken! Merging the two lists with descriptor skills first and constructor skills appended sounds reasonable. Repeated skill names can be deduplicated while preserving that order.

    For the constructor API, I suggest supporting both:

    • A list of skill names, referencing skills from sources registered through the existing APIs.
    • A Skills object, with the constructor registering its sources and making all skills from those sources available to the agent.

    Please merge skills into a copy of the chat-model descriptor’s configuration rather than modifying the supplied descriptor or its skills list in place. Users may reuse the same descriptor across multiple agents; adding skills to one agent should not affect another agent or change the caller’s original configuration.

  4. da-daken commented on Oct 9, 2026

    @da-daken
    Contributor

    @wenjin272 Thanks for the clarification. Before implementing the Skills-object form, I'd like to confirm two points.

    1. Approach A or B?

    There are two ways to resolve "all skills from these sources" at runtime:

    A: Record "source → skill names" at plan time, expand at open time. The descriptor stores a marker meaning "all skills from these sources." During open(), SkillManager loads the actual skill names from the sources and appends them to the descriptor's skill list (de-duplicated, keeping order).

    The agent only gets skills from the sources the user passed. Requires changes to the ResourceContext interface and SkillManager in both Java and Python.

    B: "Passed a Skills object" means "expose all skills the agent can see." Simpler: when the constructor receives a Skills object, the descriptor calls SkillManager.getAllSkillNames() at open() time. Every skill loaded from any source becomes available to the agent.

    The agent gets skills from all registered sources, not just the ones the user passed. Skills also carry bash execution capability, which could unintentionally expose privileged skills (e.g. a db-admin registered at the environment level by another team member).

    Which approach do you prefer?

    2. If A: Java and Python currently resolve duplicate skill names differently. OK to align Java with Python?

    When two sources define a skill with the same name, SkillManager.registerRepo simply overwrites (with a WARN log). The question is which one wins. Java and Python currently differ:

    • Python: _add_skills iterates skills_objects in insertion order. The effective order is @Skills methods → environment → agent.add_resource (including the constructor). The last one wins, so agent-level skills override environment-level ones. This matches the existing precedence for resources with the same name (env | agent.resources[type]).
    • Java: Agent.resources is a HashMap, and addResourcesIfAbsent merges environment resources into the same map, losing the level information. AgentPlan.addSkills then sorts resources by name (for determinism across JDKs, not as a precedence rule) before merging sources. The winner is simply the one whose resource name sorts last.

    Under approach A this matters more, because "skills from these sources" is part of the semantic contract — a skill from the constructor's Skills object that gets silently overwritten would disappear from the expanded name list entirely. I'd propose making Java follow a level-aware order (@Skills methods sorted by name for determinism → environment → agent level), aligning with Python.

  5. wenjin272 commented on Oct 9, 2026

    @wenjin272
    ContributorAuthor

    Thanks for outlining the options @da-daken. I prefer A: passing a Skills object should expose skills from those specific sources, while preserving any skill names explicitly configured on the chat-model descriptor.

    One clarification on timing: with cross-language repositories in #1214, skill discovery must happen at runtime, using the job’s classloader and initialized Python bridge/interpreter. At plan time, please only record the source declarations and the selection marker, not the actual skill names. At runtime, resolve the names through SkillManager, then merge them with the descriptor’s explicit names, keeping descriptor names first and deduplicating while preserving order. That final list can feed the existing prompt-generation and script-directory lookup paths.

    For the second point, aligning Java with Python’s level-aware precedence sounds reasonable: @Skills declarations → environment → agent, with later entries winning. Please document this behavior change and cover same-name conflicts across these levels in both languages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

fixVersion/0.4.0priority/majorDefault priority of the PR or issue.tech debt[Issue Type] User-unaware issues, such as code refactor and infrastructure maintenance.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions