/** * Creates a SkillBox without a toolkit. * * <p>This constructor will be removed in the next release. A SkillBox must hold a * {@link Toolkit} to operate correctly. Relying on automatic toolkit assignment makes * behavior less explicit and harder to reason about. */ @Deprecated publicSkillBox() { this(null, null, null); }
AgentSkillskill= AgentSkill.builder() .name("data_analysis") .description("Use this skill when analyzing data, calculating statistics, or generating reports") .skillContent("# Data Analysis\n...") .addResource("references/api-doc.md", "# API Reference\n...") .addResource("references/best-practices.md", "# Best Practices\n...") .addResource("examples/example1.java", "public class Example1 {\n...\n}") .addResource("scripts/process.py", "def process(data): ...\n") .build();
SKILL.md 格式规范
name: skill-name # 必需: 技能名称(小写字母、数字、下划线) description: This skill should be used when… # 必需: 触发描述,说明何时使用
/** * Builds and returns a new ReActAgent instance with the configured settings. * * @return A new ReActAgent instance * @throws IllegalArgumentException if required parameters are missing or invalid */ public ReActAgent build() { // Deep copy toolkit to avoid state interference between agents ToolkitagentToolkit=this.toolkit.copy(); if (enableMetaTool) { agentToolkit.registerMetaTool(); } // Configure long-term memory if provided if (longTermMemory != null) { configureLongTermMemory(agentToolkit); } // Configure RAG if knowledge bases are provided if (!knowledgeBases.isEmpty()) { configureRAG(agentToolkit); } // Configure PlanNotebook if provided if (planNotebook != null) { configurePlan(agentToolkit); } // Configure SkillBox if provided if (skillBox != null) { configureSkillBox(agentToolkit); } returnnewReActAgent(this, agentToolkit); }
/** * Registry for managing skill registration and activation state. * * <p>This class provides basic storage and retrieval operations for skills. * * <p><b>Responsibilities:</b> * <ul> * <li>Store and retrieve skills * <li>Track skill metadata and activation state * </ul> * * <p><b>Design principle:</b> * This is a pure storage layer. All parameters are assumed to be non-null * unless explicitly documented. Parameter validation should be performed * at the Toolkit layer. */ classSkillRegistry { privatefinal Map<String, AgentSkill> skills = newConcurrentHashMap<>(); privatefinal Map<String, RegisteredSkill> registeredSkills = newConcurrentHashMap<>(); ... }
publicstaticfinalStringDEFAULT_AGENT_SKILL_INSTRUCTION= """ ## Available Skills <usage> Skills provide specialized capabilities and domain knowledge. Use them when they match your current task. How to use skills: - Load skill: load_skill_through_path(skillId="<skill-id>", path="SKILL.md") - The skill will be activated and its documentation loaded with detailed instructions - Additional resources (scripts, assets, references) can be loaded using the same tool with different paths Path Information: When you load a skill, the response will include: - Exact paths to all skill resources - Code examples for accessing skill files - Usage instructions specific to that skill Template fields explanation: - <name>: The skill's display name - <description>: When and how to use this skill - <skill-id>: Unique identifier for load_skill_through_path tool </usage> <available_skills> """;
/** * Registers skill access tools to the provided toolkit. * * <p>This method registers the following tool: * <ul> * <li>load_skill_through_path - Load skill resources or SKILL.md content. When a resource * is not found, it automatically returns a list of available resources with SKILL.md * as the first item.</li> * </ul> * * @throws IllegalArgumentException if toolkit is null */ publicvoidregisterSkillLoadTool() { if (toolkit == null) { thrownewIllegalArgumentException("Toolkit cannot be null"); }
if (toolkit.getToolGroup("skill-build-in-tools") == null) { toolkit.createToolGroup( "skill-build-in-tools", "skill build-in tools, could contain(load_skill_through_path)"); }
/** * Creates the load_skill_through_path agent tool. * * <p>This tool allows agents to load and activate skills by their ID and resource path. * It supports loading SKILL.md for skill documentation or other resources like scripts, * configs, and templates. * * @return AgentTool for loading skill resources (including SKILL.md) */ AgentTool createSkillAccessToolAgentTool() { returnnewAgentTool() { @Override public String getName() { return"load_skill_through_path"; }
@Override public String getDescription() { return"Load and activate a skill resource by its ID and resource path.\n\n" + "**Functionality:**\n" + "1. Activates the specified skill (making its tools available)\n" + "2. Returns the requested resource content\n" + " usage instructions)\n" + "- 'SKILL.md': The skill's markdown documentation (name, description," + "- Other paths: Additional resources like scripts, configs, templates, or" + " data files"; }
@Override public Map<String, Object> getParameters() { // Get all available skill IDs List<String> availableSkillIds = newArrayList<>(skillRegistry.getAllRegisteredSkills().keySet());
return Map.of( "type", "object", "properties", Map.of( "skillId", Map.of( "type", "string", "description", "The unique identifier of the" + " skill.", "enum", availableSkillIds), "path", Map.of( "type", "string", "description", "The path to the resource file within the" + " skill (e.g., 'SKILL.md," + " references/references.md')")), "required", List.of("skillId", "path")); }
/** * Gets the skill system prompt for the agent. * * <p>Generates a system prompt containing all registered skills. * * @return The skill system prompt, or empty string if no skills exist */ public String getSkillSystemPrompt() { StringBuildersb=newStringBuilder();
// Check if there are any skills if (skillRegistry.getAllRegisteredSkills().isEmpty()) { return""; }
// Add instruction header sb.append(instruction);
// Add each skill for (RegisteredSkill registered : skillRegistry.getAllRegisteredSkills().values()) { AgentSkillskill= skillRegistry.getSkill(registered.getSkillId()); sb.append( String.format( template, skill.getName(), skill.getDescription(), skill.getSkillId())); }
// Close available_skills tag sb.append("</available_skills>");
/** * Implementation of skill resource loading logic. * * @param skillId The unique identifier of the skill * @param path The path to the resource file * @return The formatted resource content or error message with available resources * @throws IllegalArgumentException if skill doesn't exist or resource not found */ private String loadSkillResourceImpl(String skillId, String path) { AgentSkillskill= validatedActiveSkill(skillId);
// Special handling for SKILL.md - return the skill's markdown content if ("SKILL.md".equals(path)) { return buildSkillMarkdownResponse(skillId, skill); }
// Get resource Map<String, String> resources = skill.getResources(); if (resources == null || !resources.containsKey(path)) { // Resource not found, return available resource paths thrownewIllegalArgumentException( buildResourceNotFoundMessage(skillId, path, resources)); }
/** * Creates an AgentSkill with explicit parameters and custom source. * * <p>Use this constructor when you want to create a skill directly without parsing * markdown. The source parameter indicates where the skill originated from. * * @param name Skill name (must not be null or empty) * @param description Skill description (must not be null or empty) * @param skillContent The skill implementation or instructions (must not be null or empty) * @param resources Supporting resources referenced by the skill (can be null) * @param source Source identifier for the skill (null defaults to "custom") * @throws IllegalArgumentException if name, description, or skillContent is null or empty */ publicAgentSkill( String name, String description, String skillContent, Map<String, String> resources, String source) { if (name == null || name.isEmpty() || description == null || description.isEmpty()) { thrownewIllegalArgumentException( "The skill must have `name` and `description` fields."); } if (skillContent == null || skillContent.isEmpty()) { thrownewIllegalArgumentException("The skill must have content"); }
✨ Journey into the AI cosmos — where neural networks ignite curiosity, backend systems pulse with precision, and every line of code weaves the future. Dive in, explore, and transform.