Slash-command provider — examples#
A slash-command provider block in agent.hcl#
required_providers {
release-tools = {
source = "github.com/agentco/provider-release-tools"
version = "~> 1.0.0"
}
}
provider "release-tools" {
changelog_path = "CHANGELOG.md"
}
As with every other category, release-tools's category is never declared in agent.hcl — the kernel discovers it's a slashcommand.v1 provider at runtime, from its own GetCapabilities response, per configuration/blocks-reference.md#required_providers. Describe (see protocol.md#describe) is the only place category appears as an explicit field, and only for the dev_overrides identity case.
The wire protocol#
This is the wire protocol's service declaration and core call/event messages, in protobuf form (trimmed to the essentials):
service SlashCommandService {
rpc GetCapabilities(GetCapabilitiesRequest) returns (GetCapabilitiesResponse);
rpc Configure(ConfigureRequest) returns (ConfigureResponse);
rpc Invoke(InvokeRequest) returns (stream InvokeResponse);
rpc Render(RenderRequest) returns (RenderResponse);
rpc Preview(PreviewRequest) returns (PreviewResponse);
rpc Describe(DescribeRequest) returns (DescribeResponse);
}
message SlashCommandCall {
string id = 1;
string name = 2;
google.protobuf.Struct arguments = 3;
pluggableharness.common.v1.CallContext call_context = 4;
}
message PreviewRequest {
SlashCommandCall call = 1;
}
message PreviewResponse {
pluggableharness.render.v1.RenderTree preview = 1;
}
message DescribeRequest {}
message DescribeResponse {
pluggableharness.common.v1.ProducerRef producer = 1;
}
InvokeRequest/InvokeResponse are thin per-RPC envelopes ({ call = 1; } / { event = 1; }) around SlashCommandCall/SlashCommandEvent — see data-types.md#slashcommandcall--slashcommandevent.
A GetCapabilitiesResponse snippet#
release-tools declaring a single /changelog command — a TOOL_KIND_DATA_SOURCE read of the repo's changelog file, so it executes freely without going through the plan/apply gate:
← GetCapabilitiesResponse{
commands: [
{
name: "changelog",
description: "Show unreleased entries from CHANGELOG.md",
input_schema: {type: "object", properties: {since: {type: "string"}}},
kind: TOOL_KIND_DATA_SOURCE,
risk: RISK_CLASS_READ_ONLY,
concurrency: {safe: true},
streaming: false,
idempotent: true,
}
],
config_schema: {...},
supported_hook_points: [],
}
A full Invoke event sequence#
A /changelog call that reads the file and returns its unreleased section, expressed as the oneof SlashCommandEvent.event variants:
→ InvokeRequest{
call: {
id: "sc_17",
name: "changelog",
arguments: {},
call_context: {session_id: "01J...", turn_id: "01J...", working_directory: "/home/steven/code/aiagent"},
}
}
← InvokeResponse{event: {progress: {message: "reading CHANGELOG.md"}}}
← InvokeResponse{event: {result: {payload: {"unreleased": "- Add slashcommand.v1 category\n"}}}}
Because TOOL_KIND_DATA_SOURCE commands bypass the resource plan/apply gate entirely (per protocol.md#invoke), this call never produces a PlanItem awaiting approval — it dispatches and streams back immediately.
If the kernel cancels the stream mid-flight (e.g. the user interrupted the turn while /changelog was still reading), the plugin sees the gRPC stream close and — per protocol.md#invoke, reusing tool/protocol.md#invoke's cancellation contract — MUST make a best-effort report of what already happened before closing, for any TOOL_KIND_RESOURCE command in flight:
→ InvokeRequest{
call: {
id: "sc_18",
name: "release",
arguments: {"version": "1.4.0"},
call_context: {session_id: "01J...", turn_id: "01J...", working_directory: "/home/steven/code/aiagent"},
}
}
← InvokeResponse{event: {progress: {message: "tagging v1.4.0"}}}
← InvokeResponse{event: {output_chunk: {stream: OUTPUT_STREAM_STDOUT, data: "Created tag v1.4.0\n"}}}
← InvokeResponse{event: {partial_result: {payload: {"note": "tag created; changelog rewrite cancelled before it ran"}}}}
— no terminal result or error follows; the kernel's own bookkeeping records the call as cancelled once the stream closes without one, per conformance.md#error-taxonomy's cancelled category, the same reused tool.v1.ToolErrorCategory value tool/conformance.md#error-taxonomy defines.