Skills
Give a Met new capabilities — activate them from the catalog, store their credentials and link them.
A skill is a packaged capability a Met can use: talking to an external system, running a procedure, reading a data source. Instead of wiring every integration by hand, you activate the skill and the Met already knows how to use it.
Use the skills:read and skills:manage scopes.
The model in three pieces
| piece | what it is |
|---|---|
| Catalog | the skills available to your workspace — the system ones and the marketplace ones |
| Activation | the skill installed in your workspace, with its credentials and its state |
| Link | which Mets can use it. Activating it does not give it to all of them: it is linked per Met |
That third piece is the one most often missed. Activating a skill does not make your Mets use it — it has to be linked. That is deliberate: it keeps a support Met from inheriting the billing Met's capabilities.
See what's there
const marketplace = await met.skills.marketplace(); // the marketplace ones
const system = await met.skills.system(); // the ones Meteor ships
const active = await met.skills.active(); // the ones you already have active
const everything = await met.skills.all();
To find out which state each one is in:
const states = await met.skills.status();
// → [{ skill_id, active, configured, missing_credentials: [...] }, …]
const one = await met.skills.skillStatus('crm-hubspot');
configured is the one that matters before linking: a skill can be active and without credentials, and in that case the Met sees it and fails when it uses it.
Activate and configure
await met.skills.activate('crm-hubspot');
await met.skills.setCredentials('crm-hubspot', {
api_key: process.env.HUBSPOT_KEY,
});
Credentials are write-only: they are stored encrypted and no API response returns them, whole or masked. To know whether they are set you use configured from the state; to change them, you send them again in full.
Before handing the skill to a Met, test it:
const check = await met.skills.test('crm-hubspot', { /* example payload */ });
test really does run the skill against the external system, so it spends whatever that call spends. With a met_test_ key you cannot run skills that have external side effects — see Authentication.
Link it to a Met
await met.skills.linkToAgent(agentId, 'crm-hubspot');
const forThisMet = await met.skills.forAgent(agentId); // what that Met sees
await met.skills.unlinkFromAgent(agentId, 'crm-hubspot');
Unlinking does not deactivate the skill or delete its credentials: it only takes it away from that Met. To remove it from the workspace:
await met.skills.deactivate('crm-hubspot'); // keeps credentials
await met.skills.remove('crm-hubspot'); // takes it out of the workspace
Executions already in flight that were using the skill finish; the next ones stop seeing it.
Skills with MCP servers of their own
A skill can bring its own MCP servers, and you can control which ones stay exposed:
const servers = await met.skills.mcps('crm-hubspot');
await met.skills.setMcps('crm-hubspot', { /* configuration */ });
await met.skills.updateMcp('crm-hubspot', mcpId, { /* changes */ });
await met.skills.removeMcp('crm-hubspot', mcpId);
Not to be confused with MCP integrations, which are connectors you register at the workspace level: the ones here come inside the skill and live and die with it.
When a skill, and when a standalone tool
- Skill — if the capability has credentials and several operations, and you
want to switch it on or off as one unit.
- MCP integration — if you already have an MCP
server and just want Meteor to use it.
- Function — if it is your own code and you want
the Met to call it like an endpoint.
The order you almost always want:
status→activate→setCredentials→test→linkToAgent. Skippingtestis the most common cause of a Met that "has the skill" and fails on first use.