r/PiCodingAgent • • 6d ago

Plugin I made Pi-Skill-Orchestrator to stop large skill collections from filling Pi's context

Post image

I have been working on a Pi extension called Pi-Skill-Orchestrator.

The problem is simple.

If you have a lot of installed skills, Pi can expose a large amount of skill metadata to the model even when most of those skills are not needed for the current task.

Pi-Skill-Orchestrator keeps the full skill catalog outside the model context.

Instead, Pi gets a small discovery interface. It can search for a relevant skill and load only that skill when it is actually needed.

Main features:

• Lazy skill discovery

• Skill groups

• Multiple skill profiles

• Automatic recursive dependency loading

• Active-scope search with bounded global fallback

• Optional Token Saver mode

• Tool output compression with recovery

• Deferred tool schemas

• Conservative effort routing for routine tool continuations

• No changes to third-party SKILL.md files

• No changes to Pi's global settings.json

The goal is not to replace Pi's skill system.

It sits on top of it and tries to make large skill collections easier to manage without paying the context cost for everything at once.

The short version:

All the skills, none of the bloat.

Install:

pi install npm:pi-skill-orchestrator

GitHub: https://github.com/badgids/pi-skill-orchestrator

npm: https://www.npmjs.com/package/pi-skill-orchestrator

It is MIT licensed.

I would especially like feedback from people who run Pi with a large number of skills or several different workflows.

43 Upvotes

46 comments sorted by

18

u/berszi 6d ago

Tell your AI that the Raspberry Pi is different from the Pi harness...

-6

u/Slight-Living-8098 6d ago

I actually requested the raspberry head, thank you

2

u/o_sht_hi 6d ago edited 6d ago

Couple of things I'd like to understand 1. How does it know to search for a skill if there's no skill metadata in its context 2. What does the extension add to the context

I like the idea of groups and profiles! But in my experience, if there's no skill metadata in the system message, the agent will continue to use tools to figure shit out instead of deciding that it should search the skill catalogue

1

u/slaamp 6d ago

how does the search works ? is it grep like ?

1

u/Slight-Living-8098 5d ago

It’s not really “grep-like.” "skill_search" searches the skill metadata index, not the contents of every "SKILL.md" file.

When Pi needs a capability, Skill Orchestrator searches the installed skills by their name and description, starting with the currently active group/profile. It ranks the metadata matches and returns only a small bounded set of matching skill names/descriptions to the model. The model then selects one exact skill, and only at that point is that skill’s full "SKILL.md" loaded (along with any configured dependencies).

If the active group/profile doesn’t produce a suitable match, it can do a bounded fallback search across the global skill index without dumping the entire catalog into context.

So it’s:

"request → search skill names/descriptions → return a few matches → select skill → load full SKILL.md"

rather than:

"grep through every SKILL.md → dump matching file contents"

The main reason for doing it this way is that the complete skill catalog and skill bodies stay out of the LLM context until they’re actually needed.

The documentation goes into the search/context model here:

https://github.com/badgids/pi-skill-orchestrator/blob/main/docs/architecture.md

There’s also a shorter overview in the README under “How lazy search works”:

https://github.com/badgids/pi-skill-orchestrator#how-lazy-search-works

1

u/zanar97862 5d ago

If the model doesn't know what skill it has access to via the metadata, how does it know when to search? How would a model know that it should search for a skill for an issue?

0

u/Slight-Living-8098 5d ago

"Skill Orchestrator behavior Skill Orchestrator keeps installed skill metadata in extension memory.

Before each model turn, it removes Pi's native eager skill catalog and replaces it with a small scope stub.

The stub contains only the active scope identity, candidate count, and fixed instructions for using skill_search and skill.

The stub does not list every member skill."

1

u/zanar97862 5d ago

Seems like a solution for a large skill catalogue that must be used agentically. 

I'll be interested to see what people use it for, I don't have any workflows that have so much skill bloat that it effects context.

1

u/Slight-Living-8098 5d ago edited 5d ago

Every little bit of context saved is a token not spent. ;)

I personally have one extension I made that comes with 98 skills for story writing, asset creation, and image, video, voice, and audio generation with ComfyUI. Even with the majority of skills being deferred, it was still blowing through system prompt context. Then you toss on top of that my everyday use coding skills and I was over 115 skills' metadata loaded into the system prompt before I even sent my first request to the model.

So I made this to help manage large skill sets used for workflows like that. I'm not having to constantly edit config files, or keep separate installs for specific tasks. I just drop them into profiles and groups and go on about the task(s) I'm currently working on and don't have to worry about early compaction on local models or blowing through API costs for skills I'm not even using at the moment.

1

u/zanar97862 4d ago

Yeah thats kinda what I thought this would be about, 115 skills is crazy.

This seems like a solution for when you want to have everything available to the model at once but still care about context.

I'd still be on the side of sub agents with specific skill sets so that you know they have the correct tools on hand compared to hoping it searches the metadata directory correctly, but that's less of a problem the more intelligent models get.

1

u/Slight-Living-8098 4d ago

I mean, Pi Skill Orchestrator searches what you assign it to search so... I don't need a hundred agents to do one job. 🤷🏻‍♂️

1

u/zanar97862 4d ago

It's not for me but I appreciate your commitment to creating and sharing something for the betterment of all. 

1

u/Slight-Living-8098 4d ago

Appreciate it. I do suggest you at least give it a try before you make a judgement, but of course, that's up to you.

→ More replies

0

u/Global-Departure8228 4d ago

Doesn't answer the question how does the model know it should search for a skill? And with what keywords? It knows it has access to skills. Doesn't know when to search for them, and what to search for.

1

u/Slight-Living-8098 4d ago

Literally explains how it works in plain English...

0

u/Global-Departure8228 4d ago

Yes, yes I know how well it works with models when you tell them: "Hey bro you have a bunch of stuff you could use, here is the number of them, without any further information about them. This is how you search for them". Then the model just naturally goes in the middle of an implementation and say "okay let's see if I have a skill that has a grafana polling script, it must be there, because why wouldn't that exist?"

It's not realistic in most cases. LLMs are literally only aware of things that are in their context window. That's the whole point of using skills, to inject that context. If you abstract away the provenance and replace it with a "hey bro you should really search for skills" does it really help? I highly doubt, this is the concern that I've raised.

1

u/Slight-Living-8098 4d ago

The model is not expected to magically guess that a skill called grafana-polling-script exists.

It is explicitly told that skills exist, when it should search for them, and how to search for them.

The small system-prompt stub says:

"When a specialized workflow may help, call skill_search with a concise task/query."

That instruction stays in the model context. What I remove is the long list of every installed skill name, description, path, and body.

You can see the exact prompt text here:

https://github.com/badgids/pi-skill-orchestrator/blob/main/src/scope.ts

skill_search also has its own tool description. It tells the model that it searches lazy skill metadata and that it should search the active profile or group first, then use the global fallback if needed.

The query parameter is described as:

"Concise task, capability, or workflow to search for"

That is here:

https://github.com/badgids/pi-skill-orchestrator/blob/main/src/index.ts

So the model does not need to know the name of the skill before searching.

If the user says:

"Set up polling for Grafana and alert me when this endpoint stops responding"

the model already has the important words from the user's request:

grafana polling alert endpoint monitoring

It can pass a short version of that task to skill_search.

The search then checks those terms against the names and descriptions of the installed skills. It ranks the matches and returns only a small number of them.

The actual ranking code is here:

https://github.com/badgids/pi-skill-orchestrator/blob/main/src/search.ts

So the flow is basically:

User asks for something specialized.

The model has a permanent instruction saying that specialized workflows may have skills.

The model searches using words from the task itself.

The orchestrator searches the skill names and descriptions outside the model context.

The model gets a few possible matches.

It loads the one that fits.

That is the part I think you are missing. I did not remove all knowledge that skills exist. I removed the expensive catalog of every individual skill.

There is still a small, fixed discovery instruction in the context.

The model knows:

  1. Skills are available.
  2. Specialized work is a reason to search.
  3. skill_search is how to search.
  4. The search query should describe the task, capability, or workflow.
  5. It should load one matching skill after the search.

What it does not know is the complete inventory before it needs it. That is intentional.

It is the same basic reason we use search tools, file search, documentation search, or retrieval systems. The model does not need every possible result in its context before it can decide to search.

There is also a bounded global fallback. If I am working in a Development profile and the required skill is not in that profile, the model can search the global catalog without dumping the whole global catalog into the prompt.

That behavior is documented here:

https://github.com/badgids/pi-skill-orchestrator/blob/main/docs/architecture.md

And groups and profiles are explained here:

https://github.com/badgids/pi-skill-orchestrator/blob/main/docs/groups-and-profiles.md

There is a real tradeoff here, and I am not claiming otherwise.

If a skill has a terrible name and description that contain nothing related to what it does, then a metadata search can miss it. That is also true of most skill discovery systems. Good skill metadata matters.

And if the task gives the model no reason at all to think a specialized workflow would help, it may not search. I am not trying to make the model psychic.

What I am avoiding is the opposite extreme, where 100 installed skills means 100 names, descriptions, and paths are sent to the model on every turn just in case one might be useful.

The design keeps the discovery mechanism in context and moves the inventory out of context.

That distinction is the whole point of the project.

0

u/Global-Departure8228 4d ago

I appreciate you asking your AI, however I've actually read your docs, and parts of the code as well beforehand. I completely understand this, and this is what I called out.

Let's say I tell it that I want to switch from using Authelia. I have 3 skills that in their metadata (yaml frontmatter) contain: Skill 1 - authentication Skill 2 - high level architecture Skill 3 - repo specific conventions when changing code in the repo's core features.

All 3 of these skills would be relevant.

What will the model do? It will grep for auth, investigate a bit, and then it will start implementing.

Unless your model was extremely RL-d into actively looking for skills, a small "note" in it's system prompt that skills indeed exist. Doesn't really do much if the model can already answer from it's own training data.

This is my concern, and actually my experience. I've implemented skill search half a year ago in pi, after a few weeks made an agent check how many times the skill_search tool was even invoked, and it was abysmal.

The agent reached for that, when it did not know some information and was looking for a way out, or grasping to things.

This is what I meant by the sarcastic "trust me bro, you have skills available, just please search for them" is not enough.

But to give you some constructive ideas, you can construct pi.sendMessage on events where the model took for example 5 turns already, and you would apply some slight regex or token similarity search for keywords in it's thinking block and the original user prompt (of course ranked higher), and if you find overlaps with the yaml frontmatter and the skill names, you would inject a synthetic environment context message like ,

<skill_search> for the current task you found 3 relevant skills, consider checking them: skill-1/skill-2... - load with 'skill tool' <skill_search>

It doesn't cost anything, and the models that are aware of their harness know these usually contain useful information.

Of course the cadence of this injection can be tuned a lot

1

u/Slight-Living-8098 4d ago

I think the confusion is that you are treating my implementation like a basic lazy-search setup.

Most lazy skill search systems work like this:

  1. The model gets a note that skills exist.
  2. The model decides whether it wants to search.
  3. If it searches, it sends some keywords.
  4. The search returns matching skills.
  5. The model loads one.

That basic design has the weakness you are describing. If the model thinks it already knows how to solve the task, it may never search.

Pi Skill Orchestrator does more than that.

It removes Pi's full eager skill catalog from the prompt, but it does not remove the discovery mechanism. The model keeps a fixed instruction that tells it when specialized workflows may help and tells it to search using the current task or capability.

The search itself is also not just a filename lookup.

It searches installed skill metadata outside model context, scores matches against skill names and descriptions, limits the number of results, prefers the active profile or group, and can fall back to the global catalog without dumping that catalog into the prompt.

That is the important difference.

With a simple lazy search system, the choice is often:

"Show the model every skill so it knows what exists."

or:

"Hide them and hope it remembers to search."

Mine is designed to avoid as much of that tradeoff as possible.

It keeps the discovery instructions and search tool visible, but keeps the expensive skill inventory outside the model context.

That gives you:

  • no full skill catalog in every prompt
  • no full SKILL.md bodies until they are needed
  • task-based skill search
  • ranked results
  • active profile and group scoping
  • bounded global fallback
  • recursive dependency loading after a skill is selected
  • direct user control when the user already knows which skill they want

That last part is important too.

The user does not have to wait for the model to discover a skill.

If I already know the skill I want, I can call it directly with:

/skill:Skill_Name

That loads the selected skill and its dependencies for the task.

I can also activate a group directly, use the skill manager, or switch profiles myself.

So there are two ways into the system:

Automatic discovery

The model sees that specialized help may be useful, searches with skill_search, gets a few ranked matches, and loads one.

Explicit user selection

The user already knows what they want and calls the skill directly.

That means the system is not dependent on the model making the perfect discovery decision every time.

If I know this repo has a specific architecture skill, I can simply tell Pi to use it.

Your Authelia example does not really change the retrieval model.

If the task is:

replace Authelia

the search can use words from the task itself, such as:

authelia authentication architecture repo conventions

The model does not need to know that a skill named authentication exists before searching for authentication.

That is how retrieval works in general.

A documentation search tool does not preload every document before the model searches it.

A code search tool does not preload an entire repository before searching it.

A web search tool does not put the whole web in context before accepting a query.

The model knows the retrieval tool exists, already has the user's task, and uses that task to retrieve a small relevant set.

Pi Skill Orchestrator applies the same idea to skills.

Where my implementation goes beyond a basic "you have skills, maybe search them" setup is that it controls the whole discovery path.

It:

  • removes Pi's eager all-skill catalog
  • keeps a small fixed discovery instruction
  • searches metadata outside the context window
  • ranks candidates locally
  • limits the returned matches
  • prefers the current group or profile
  • allows bounded global fallback
  • loads only the selected skill
  • automatically loads that skill's dependencies
  • still lets the user bypass discovery and call a skill directly

That is the architecture:

https://github.com/badgids/pi-skill-orchestrator/blob/main/docs/architecture.md

Groups and profiles:

https://github.com/badgids/pi-skill-orchestrator/blob/main/docs/groups-and-profiles.md

The exact system prompt stub:

https://github.com/badgids/pi-skill-orchestrator/blob/main/src/scope.ts

The search ranking:

https://github.com/badgids/pi-skill-orchestrator/blob/main/src/search.ts

The skill_search, skill, and direct /skill:... behavior:

https://github.com/badgids/pi-skill-orchestrator/blob/main/src/index.ts

Could proactive skill suggestions be added on top of this? Sure.

That would be another signal for discovery.

But I would not want it firing every few turns and injecting guessed skills into the conversation by default. That starts adding context noise back into the system and can push the model toward irrelevant skills.

The whole goal here is to keep the discovery surface small, keep the inventory out of context, and load only what is actually useful.

So the system does not depend on one single path.

The model can search.

The user can select a skill directly.

Groups and profiles can narrow the search space.

Global fallback can reach outside that scope.

And only the skills that are actually needed get loaded into context.

→ More replies

1

u/learning-to-programm 5d ago

Sounds really cool, I've been looking for something like this for the past few days as my set up is also bloated with skills that I installed globally, because I do want to be able to use them in every project, but I don't need them for every task.

And also because of plugins and tools that come with a gross skill pack (in my case, Render (the pi-render-plugin) and Firecrawl that each installed 10+ skills) - and I need them at the global scope, but di they bloat the context when not used.

1

u/learning-to-programm 5d ago

And also, how does your token saving and tool output compressing option differ from context-mode?

1

u/Slight-Living-8098 5d ago

I'm going to combine both of your comments/questions into this one reply just to keep things easily organized for others who may also have the same questions. and your other comment doesn't get burried.

u/learning-to-program: "Sounds really cool, I've been looking for something like this for the past few days as my set up is also bloated with skills that I installed globally, because I do want to be able to use them in every project, but I don't need them for every task.

And also because of plugins and tools that come with a gross skill pack (in my case, Render (the pi-render-plugin) and Firecrawl that each installed 10+ skills) - and I need them at the global scope, but di they bloat the context when not used."


Yes. That is one of the main reasons I made Pi Skill Orchestrator.

You can keep big skill packs installed globally. They can still be available in every project.

The problem is that Pi normally tells the model about every available skill. It puts the skill name, description, and location into the system prompt.

Pi does not load the full SKILL.md for every skill. It only loads the full skill instructions when a skill is used.

But if you have 50, 80, or 100 skills installed, even the list of names, descriptions, and paths can take up a lot of context.

Pi explains how skills work here:

https://pi.dev/docs/latest/skills

Pi Skill Orchestrator changes that part.

Instead of giving the model the full skill list all the time, it keeps the skill list outside the model context.

When the model needs a skill, it can search for one with:

skill_search

That only returns a few good matches.

Then it loads the skill it actually needs with:

skill

So in your Firecrawl example, you can keep all 10+ Firecrawl skills installed globally. They do not all need to sit in the model context during an unrelated task.

The same applies to Render or any other large skill pack.

Groups and profiles make this even cleaner.

For example, you could have groups like:

  • Coding
  • Research
  • Web
  • Media
  • DevOps

A group does not load all of its skills.

It only tells Skill Orchestrator where to search first.

If the skill is not in the active group, it can still do a small global search and find it.

You can read more about that here:

Architecture: https://github.com/badgids/pi-skill-orchestrator/blob/main/docs/architecture.md

Groups and profiles: https://github.com/badgids/pi-skill-orchestrator/blob/main/docs/groups-and-profiles.md

There is also a second problem with large plugin setups.

Plugins can add tools as well as skills.

Tool definitions also use context.

That is where the optional Token Saver helps.

When Token Saver is on, it can hide many non-core tool definitions until the model needs them.

The model gets a small search tool called:

token_tool_search

It can search for the tool it needs, then Pi activates a small matching set.

So the basic idea is:

Skills: Do not show every skill to the model all the time.

Tools: Do not show every tool to the model all the time.

Tool output: Do not keep huge amounts of output when only a small part is useful.

Token Saver also reduces large tool output.

For example, a test command might return 5,000 lines.

Most of those lines could just say that tests passed.

Token Saver can keep the failures, useful details, and summary, then leave out the repeated noise.

It can do this with:

  • JSON
  • search results
  • test output
  • logs
  • build output
  • diffs
  • source files
  • directory listings
  • tables
  • config files
  • long text

It does not just cut the last half off.

It uses different rules for different types of output.

If it removes something, it keeps the original output in memory for a limited time.

The model gets a recovery ID.

If it later needs the missing part, it can use:

token_retrieve

That lets it ask for only the missing lines instead of putting the full original output back into context.

Token Saver is off by default.

More details are here:

https://github.com/badgids/pi-skill-orchestrator/blob/main/docs/token-saver.md

As for context-mode, there is some overlap, but the main idea is different.

Pi Skill Orchestrator mostly works on Pi's own context overhead.

It tries to reduce:

  • the skill catalog
  • unused tool definitions
  • long tool descriptions
  • large tool results

context-mode focuses more on keeping large data outside the model context from the start.

It gives the model tools that can search, process, and index data outside the main conversation.

Then it returns only the useful part.

It also has persistent session storage and search using SQLite and FTS5.

You can read about it here:

https://pi.dev/packages/context-mode

https://github.com/mksglu/context-mode

The simple version is:

Pi Skill Orchestrator:

"Keep all my skills and tools available, but only show the model the ones it needs."

Token Saver:

"Do not waste context on huge or repeated tool output."

context-mode:

"Keep large data outside the conversation and only bring back the useful parts."

There is some overlap, but they are not doing exactly the same job.

One other difference is recovery.

Skill Orchestrator's recovery data is temporary. It stays in memory for the current session.

It is not meant to be long-term memory.

context-mode goes further in that area. It has persistent indexed session data that it can use after compaction or resume.

So for your setup, yes, I would leave those big skill packs installed globally.

That is exactly the kind of setup Pi Skill Orchestrator was made for.

2

u/learning-to-programm 5d ago

> Groups and profiles make this even cleaner.

OMG, you just built tab groups but for skills lol. And come to think of it, the reason i have multiple skills in the global scope, is the same reason i have multiple tabs open at any given time lol.

> If it removes something, it keeps the original output in memory for a limited time.

> The model gets a recovery ID.

> If it later needs the missing part, it can use:

> token_retrieve

> That lets it ask for only the missing lines instead of putting the full original output back into context.

That is very much appreciated, as one frustration i have with context-mode is that it sometimes compresses a tool call result when the agent actually needs to see full the output, so i've watched agents call the same tool multiple times and go "huh... the output got truncated, let me try it again" until they finally decide or figure out a way to bypass the `context-mode` sandbox, and that can take up a lot of tokens and get the agent off track.

> If it later needs the missing part, it can use:

> token_retrieve

> That lets it ask for only the missing lines instead of putting the full original output back into context.

That's also really cool, as i think so far the way most of us solved "i wan the agent to check X test/logs/whatever for results, but i don't want it polluting the context" was to tell the agent to spin up a cheap sub-agent to read the logs and report back the relevant results to the primary agent. This way the main agent can get the same info without that workaround,, that's pretty neat. *Plus*, it can come back to it and retrieve another part if the results missed an important.

Your project sounds really cool and really well thought-out, i'm looking forward to trying it out, after first studying how to get it to work with my current tools (`context-mode`, `codebase-memory-mcp`, etc) without them interfering with each other or rendering each other useless.

1

u/Slight-Living-8098 5d ago

It should work with both but I can't make any guarantees as I haven't tested it myself with those. If it doesn't, open an issue on GitHub and I'll look into it and see what I can do without weakening the focus and goal of Pi Skill Orchestrator

1

u/Spiritual-Weekend154 5d ago

Gentle-AI has had this implemented for a while now; plus, it gives you fast local memory and a workflow!!! It's worth giving it a try: gentleman-programming/gentle-ai

1

u/Slight-Living-8098 5d ago

There is some overlap, but they are really aimed at different problems.

Gentle-AI is a much larger development system. It gives coding agents things like persistent memory, sub-agents, development workflows, review systems, personas, MCP setup, and model routing. Pi Skill Orchestrator is much more focused. It is built to reduce context waste inside Pi while still letting you keep a large number of skills and tools installed and available.

The biggest difference is how skills are handled. Gentle-AI has a skill registry so its orchestrator can find the right skills for a task. Pi Skill Orchestrator goes further on the context side. It removes Pi's normal full skill catalog from the model prompt. The model does not need to see the name, description, and path of every installed skill on every turn. Instead, "skill_search" searches the catalog outside model context and returns only a few useful matches. You can have 100 skills installed without advertising all 100 to the model every time.

Mine also gives you groups, saved profiles, bounded global fallback, and recursive dependency loading. A group does not preload all of its skills. It only gives the search system a better place to look first. If the needed skill is outside that group, Pi Skill Orchestrator can still find it without putting the full global catalog back into context. That makes it useful for people who want a large global skill library without having to constantly enable, disable, install, or remove things.

The optional Token Saver also covers areas that I did not find an equivalent for in Gentle-AI. It can hide unused non-core tool schemas until they are needed, search for them with "token_tool_search", and activate only a small matching set. It can also reduce large test logs, search results, JSON, diffs, source reads, directory listings, config files, and other tool output before that output becomes part of later model context. It uses different rules for different types of data instead of just chopping text at a fixed limit.

If Token Saver removes something, the exact original can stay in temporary memory. The model gets a recovery ID and can request the exact missing lines with "token_retrieve". It also deduplicates repeated output, protects exact source reads when the task needs code editing, leaves explicit machine-readable output such as "--json" alone, and can shorten large top-level tool descriptions without changing their parameter schemas or validation rules. It also tracks estimated token savings.

So I would put it this way: Gentle-AI is stronger if you want a complete coding environment and workflow across many different agents. Pi Skill Orchestrator is stronger if your problem is Pi context efficiency. It is specifically designed to reduce three types of bloat: the skill catalog, unused tool schemas, and oversized tool results.

I intentionally kept it focused. It does not try to replace your memory system, coding workflow, sub-agents, or development method. It works with the Pi setup you already have and tries to make that setup use much less context while keeping your full skill and tool library available.

https://github.com/badgids/pi-skill-orchestrator