Haystack v3 - Agentic Skills

I have a bunch of skills inside my .agents/skills directory. Now the question boils down to how to integrate/reuse on haystack workflows. Support for the same is added in the latest Haystack release where the introduction of FileSystemSkillStore and SkillToolset addresses the problem.
๐ FileSystemSkillStore
This takes your skills directory path as input and rest of the magic happens under the hood.
Let's understand this with the help of a example. Install a skill, using haystack-skills/haystack a skill written by me as a reference ๐:
โ npx skills add srini047/haystack-skills@haystack
โ tree .agents/skills -d
.agents/skills
โโโ haystack
โโโ references
โโโ scripts
4 directories
Please verify whether it contains a similar directory structure based on the skill you installed and at the right location (either global or project level).
from haystack.skill_stores.file_system import FileSystemSkillStore
SKILLS_PATH = ".agents/skills" # Change as per you installed location
skill_store = FileSystemSkillStore(SKILLS_PATH)
print(f"Available skills under {SKILLS_PATH} are:")
available_skills = skill_store.list_skills()
for skill in available_skills:
print("- ", skill)
print()
# Output
# (learn-haystack) โ learn-haystack git:(master) โ uv run src/3_agent_skills.py
# Available skills under .agents/skills are:
# - haystack
This is the bare minimum requirement to load the skill store. This object holds each and every reference to all the skills available inside the directory. We can list, view, read, and load the skills using this object.
One nice thing about the working is the skills aren't loaded by default. It only reads the frontmatter of the SKILL.md file during the warm_up. The rest of the content is read incrementally when the tool calls this skill.
Now that we have the skills object ready to use let's see how to convert this into a tool for use by the Haystack Agent.
๐ ๏ธ SkillToolset
This toolset helps agents discover the local skills similar to how claude code/openai codex reads the skills initially focussing the front matter and bloating the context window with the actual skill file when required. It takes a SkillStore as the input. Either use the default FileSystemSkillStore or implement your own SkillStore from scratch.
The read_skill_file method returns the most common content types i.e:
| Type | Return Type |
|---|---|
| Text | String |
| Image | ImageContent |
| FileContent |
You cannot add a skill midway once the object is created. Safest and the best way is to recreate the FileSystemSkillStore and SkillToolset objects from scratch by terminating and executing again.
All it takes to load the skills inside the agent as a tool is just a single line.
from haystack.components.agents import Agent
from haystack.tools import SkillToolset
from haystack_integrations.components.generators.cohere import CohereChatGenerator
def cohere_llm_generator(model: str = "command-a-03-2025") -> CohereChatGenerator:
return CohereChatGenerator(model=model)
skills_toolset = SkillToolset(skill_store)
haystack_skills_agent = Agent(
chat_generator=cohere_llm_generator(),
tools=[skills_toolset], # Loads all the available skills from the SkillStore, in our case it's a `FileSystemSkillStore`
)
This makes the agent aware of the available skills for its use. To make the understanding very clear, pun intended:
Use Haystack Skills inside Haystack to create a Haystack Skill Agent ๐
All that is left now is to execute the agent and see if it make the right usage of our skills.
result = haystack_skills_agent.run(
messages=[ChatMessage.from_user("How to create a simple indexing pipeline?")]
)
๐ป Sample Output
Given the query is very generic the expectation is agent to make use of Haystack Skill to provide the indexing pipeline output. You can view the output of the execution here. Complete code can be found here.
โ Conclusion
Feel free to check out the details of the latest Haystack v3 release.





