SkillSource for a catalog that changes without redeployment.
Each skill uses the Agent Skills directory format:
SKILL.md action-oriented. Move schemas, background, long examples, and conditional detail into referenced files.
Runtime behavior
ADK and LangGraph receive the samelist_skills, load_skill, and load_skill_resource tools. list_skills returns each skill’s source, ID, name, description, and version. Skill bodies and resources load only after selection.
Harnest ranks filesystem skills by name and description, then reranks bounded candidates across sources. If a query finds nothing, it ranks one fallback page without loading skill bodies.
A root skill belongs to the root agent. A folder SubAgent can own private skills; its parent does not inherit them. Skills do not add tools or MCP connections.
Use an Agent Plugin to distribute reusable skills, optionally with the MCP servers that supply their operations. Skills-only plugins are supported.
Automatic selection with decisions
Enable decision-backed skill selection on an individual managedAgent. It works with ADK and LangGraph and is off by default:
agent.py
decisions context resource using the existing decision-provider contract. The selector can use Jev or another provider; it does not construct a client or read provider credentials. A registry used only for skill selection can have bindings=() because Harnest builds its definitions dynamically. Omit provider when the registry contains exactly one provider; otherwise specify its registered name.
What reaches the decision provider
Selection uses the current agent’s authorized catalog, including filesystem, plugin, extension, and dynamic sources. Each candidate becomes aChoice question with select and skip outcomes. The provider must support QuestionKind.CHOICE and, for multiple candidates, batching. Questions include candidate identity, version, description, and selection instructions.
The input callback receives the existing SkillContext, not a separate selection context. During automatic selection, context.task is the current textual task and context.state is a read-only JSON snapshot of session/native application state with conversation messages and private Harnest channels excluded. These two properties are unavailable outside that selection scope. Existing identity, claims, storage, credential resolution, and exported resources retain their usual access boundaries.
The callback may be synchronous or asynchronous and must return a JSON-compatible mapping. Its return value is the complete DecisionRequest.state["input"] payload; Harnest does not merge additional task, identity, metadata, history, or state into it. Without a callback, this payload is just {"task": context.task}. Candidate questions are constructed separately, so a callback field cannot replace the authorized candidates. Skill bodies are not sent to the decision provider.
Loading and fallback
Exact$skill-id mentions within the visible candidate page are loaded before automatic choices, up to max_skills. Normal skill tools remain available, including when the model needs to follow another explicit request or discover candidates beyond the bounded page. Automatic selection does not grant tools, execution permission, or access to another agent’s skills.
Selected instructions are added to model requests, not session history, and reused for the same agent and task within an invocation. Later invocations rediscover the catalog. Catalog order breaks ties above max_skills; selecting none is valid.
timeout_seconds defaults to 10 and bounds discovery, input preparation, provider evaluation, and loading together. The registered decision provider’s own timeout also applies. Failures fall back to normal discovery with DecisionSkillSelector.DISCOVERY; choose DecisionSkillSelector.ERROR to stop with a redacted SkillSelectionError. These are SkillSelectionFallback enum members; string values are rejected. Cancellation propagates and existing version pins are never silently replaced.
Dynamic sources
ImplementSkillSource in harnest.lib when skills come from an API or database:
lib/wex.py
lifecycle/:
lifecycle/skills.py
list, load, and load_resource run inside an invocation and receive SkillContext with the active agent, verified user and non-secret claims, session, credentials, storage, and resources.
Apply authorization, search, ordering, and pagination in the source. Return only descriptors visible to
context.agent_name, context.user_id, and context.claims.SkillSource.list(query=...) can use your database’s text or vector search. Return the strongest candidates first; your application owns embedding costs, indexing, privacy, and invalidation.
Application code accesses the same registry through context.skills. Loaded versions stay pinned for the invocation.
Manage dynamic skill caching
Choose cache scope, keys, and invalidation without weakening Harnest’s version guarantees.
Authoring skill versus runtime skills
harnest skills install installs coding-agent guidance outside the agent’s runtime skills/ directory. It does not add runtime skills to the compiled agent.
agents, claude, codex, copilot, and cursor; omit --target for automatic detection. Existing installations are preserved unless you pass --force to replace the bundled skills. For Studio examples, see company packs and UI customization.