feat(plugin): add programmatic tool invocation support (PTC)
What does this PR do?
Introduce Programmatic Tool Calling (PTC) support for plugins, enabling plugins to invoke tools directly within a session without relying on LLM vendor-specific APIs.
This change exposes a unified tool invocation API that:
- Allows plugins to execute tools programmatically
- Reduces LLM round-trips and token consumption
- Decouples plugin PTC implementation from underlying model providers (e.g. Anthropic-specific APIs)
To support this, the JS SDK (v1/v2) is regenerated to expose the new execute API and related types, allowing plugin authors to implement PTC in a provider-agnostic way.
Without this change, plugins in opencode can only achieve PTC via vendor-dependent LLM APIs and cannot invoke tools directly.
[1] https://platform.claude.com/cookbook/tool-use-programmatic-tool-calling-ptc
Closes https://github.com/anomalyco/opencode/issues/4713
How did you verify your code works?
I've written a POC plugin to wrap the tools into async javascript functions, and the model is able to create 10k TODOs or 10 subtasks concurrently with the new interface.
Because it currently depends on a local SDK version, it has not been released yet. I will complete it as soon as possible and open-source it under the MIT license.
The following comment was made by an LLM, it may be inaccurate:
No duplicate PRs found
Hi @rekram1-node,
I’d appreciate your thoughts or guidance on this PR.
I’ve already implemented a plugin that uses features in this PR, available at https://github.com/yuguorui/opencode-ptc.
Technically, the plugin exposes the Tools available in the opencode runtime as asynchronous JavaScript functions and provides an execution environment that allows an LLM to write Javascript to call these tools programmatically. This enables more structured tool-driven workflows, such as tracking and updating large numbers of TODOs, or spawning multiple long-running background agents to analyze different parts of a codebase concurrently.
This PR changes tools from being purely prompt-level descriptions into runtime-invokable primitives that can be controlled by the model itself. Once tools are exposed at this level, use cases such as asynchronous invocation, long-running background agents, and large-scale task tracking are not “additional features”, but the minimal set of behaviors that validate the abstraction.
Without the mechanisms introduced in this PR, these workflows would be impossible to express cleanly.
Here is a simple demo:
Thank you for your time and patience.