Steps 1–3 gave you a manifest with no tools. Most agents call at least one capability—here you add a binding on the Agent and connect a worker that implements it.
Add a binding on the Agent
Add a spec.tools entry on your agent.yaml. The ref identifies the tool; as is the name the model sees. Put schema and side-effect class in the Tool file—bindings only need those fields when you narrow or override (see Tools).
spec:
tools:
- ref: weather.get-forecast
as: get_forecastReusable Tool document (optional)
For shared capabilities, define a separate kind: Tool file in a tools/ folder. The binding's ref uses namespace.name without a version suffix—the runtime resolves the Tool file's metadata.version. See Tool resource.
apiVersion: phrony.com/v1
kind: Tool
metadata:
name: get-forecast
namespace: weather
version: 1.0.0
spec:
description: Look up the weather forecast for a city.
side_effect_class: read_only
input_schema:
inline:
type: object
properties:
city:
type: string
required: [city]Validate and publish
$ phrony agents validate ./my-agent/agent.yaml
$ phrony agents publish ./my-agent/agent.yaml
$ phrony agents deploy default/my-agent@0.2.0Bump metadata.version whenever you publish a changed manifest.
Connect a worker
The runtime does not run your tool code. A worker process dials the runtime, registers weather.get-forecast@1.0.0, and handles invoke messages on the Work gRPC stream.
Tool dispatch
phrony-runtime
session
your worker
your code
Runtime dispatches invoke to your worker
A minimal TypeScript worker using the Phrony SDK connects to the runtime, registers weather.get-forecast@1.0.0, and runs your handler on each invoke:
import { Worker } from "@phrony/sdk";
const worker = new Worker({
runtimeAddr: process.env.PHRONY_RUNTIME_ADDR ?? "127.0.0.1:7777",
workerId: "weather-worker-1",
});
worker.registerTool({
tool: "weather.get-forecast",
version: "1.0.0",
maxConcurrency: 4,
async handler({ city }: { city: string }) {
// Your integration: HTTP API, database, internal service, etc.
return { temp_c: 12, conditions: "cloudy", city };
},
});
await worker.connect(); // dial runtime, register handlers, process invoke messagesDispatch flow, failure modes, and integrity checks: Tool dispatch.
What you end up with
Put it together: the Tool file defines the capability (description, schema, side-effect class); agent.yaml only wires it with ref and as. The binding ref must match the Tool identity (weather.get-forecast here).
apiVersion: phrony.com/v1
kind: Agent
metadata:
name: my-agent
namespace: default
version: 0.2.0
secrets:
openai:
fromEnv: OPENAI_API_KEY
spec:
purpose: Answer questions clearly and concisely.
instructions:
text: |
You are a helpful assistant. Be accurate and concise.
model:
provider: openai
name: gpt-4o
tools:
- ref: weather.get-forecast
as: get_forecast
output:
format: text