The Agent That Writes Its Own Tools
Elyra 0.9.3 ships extension_write — the agent can now author its own extensions, with your sign-off.
Elyra's extension_write — self-extensibility, completed
Elyra has always been "self-extensible." You can teach it new tools by writing extensions — small TypeScript files that register tools the agent can call. We've shipped dozens: Laravel tools, database tools, a YouTrack integration, Docker, and more.
But there was always an asymmetry. The human extended the agent. The agent itself, when it ran into a wall — "I keep needing to call this internal CLI, but I have no tool for it" — could only shell out to bash over and over.
Version 0.9.3 closes that gap. The agent can now write its own extensions. When it repeatedly needs a capability it doesn't have, it builds the tool.
The progression
A few releases ago we gave the agent self-writing skills — the ability to save hard-won knowledge as reusable markdown. This is the natural next step:
Skills are knowledge: "here's how Stripe webhooks work in this project."
Extensions are capabilities: "here's a tool that talks to the Stripe API."
Skills teach the agent. Extensions give it new hands. Now it can author both.
How it works
When the agent decides it needs a recurring capability, it calls extension_write with the name, a description, and the actual TypeScript source:
elyra.registerTool({
name: "deploy_status",
label: "Deploy Status",
description: "Check the status of a deployment by ID",
parameters: Type.Object({ id: Type.String() }),
async execute(_id, params) {
// ... calls your internal deploy API ...
},
});
Elyra validates it before writing — the code must have a default export and actually register a tool, so the agent can't save something broken:
export function validateExtensionCode(code: string): string | null {
if (!/export\s+default\b/.test(code)) {
return "extension code must have a default export";
}
if (!/registerTool\s*\(/.test(code)) {
return "extension code should register at least one tool";
}
return null;
}
Then you see a proposal:
─────────────────────────────────────────────
Elyra wants to add a new tool. Save it as an extension?
deploy-status.ts (project)
Check deployment status via the internal deploy API.
Review the code before approving — extensions run with full access.
> Save extension
Discard
─────────────────────────────────────────────
Approve, and deploy-status.ts lands in your extensions directory. After a /reload, the agent has a deploy_status tool it can call from then on.
The crucial guardrail
Extensions are code that runs with full access. An agent writing executable code that then runs in your environment is powerful and, handled carelessly, dangerous. So the design takes safety seriously:
Approval by default. The agent proposes; you review the code; you decide. The confirmation dialog explicitly warns you to read it.
A loud reminder. "Extensions run with full access" is right there in the prompt, every time.
Opt-in autonomy. Power users who trust the flow can enable "Auto-save extensions" in
/settings, but it's off by default.
This is the same philosophy as self-writing skills: the agent gets the magical capability, but you keep the veto until you explicitly hand it over.
Where it fits
The agent is told to use this sparingly — bash for one-offs, skills for knowledge, and extension_write only for capabilities that are clearly recurring. You don't want a new tool scaffolded for every passing need. You want one when the agent notices it's been doing the same awkward multi-step dance five times and could wrap it in a proper tool.
That's the dream of a self-extensible agent: not one you have to keep teaching, but one that notices its own gaps and fills them — with your sign-off.