Build Channels and Auth Providers
Normalize a custom protocol into canonical events and authenticate ingress with bounded identity evidence.
Before you begin
Choose the protocol, Agent labels and selector, and customer identity mode. Use the platform Constal API Key provider for Constal keys; write an Auth Provider only for external proof such as signed webhooks or third-party bearer tokens.
Steps
- Define authentication. Return only a stable subject, optional downstream customer external id, bounded claims, and optional expiry:
import { authProvider } from "@constal/sdk";
export default authProvider({
id: "signed-webhook", version: "1.0.0",
needs: [{ binding: "verifier", kind: "service", ops: ["verify"] }],
async authenticate({ request, ingress }, context) {
const proof = await context.invoke<{ valid: boolean; subject?: string }>(
context.resources.verifier!, "verify", { ingress, headers: request.headers, bodyBase64: request.bodyBase64 },
);
return proof.valid && proof.subject
? { authenticated: true, subject: proof.subject }
: { authenticated: false, reason: "invalid signature" };
},
});- Define the Channel after the Auth Provider has a stable CRN:
import { authProviderName, channel } from "@constal/sdk";
export default channel({
id: "webhook", version: "1.0.0", public: true,
authProvider: authProviderName("crn:constal:production:acme:default:auth-provider/signed-webhook"),
protocol: {
id: "json-webhook", version: "1",
receive(request) {
const body = JSON.parse(atob(request.bodyBase64 ?? ""));
return { id: body.id, type: "message", session: body.session, data: body.message };
},
respond(result) {
return { status: result.status === "failed" ? 500 : 200,
headers: { "content-type": "application/json" }, bodyBase64: btoa(JSON.stringify(result)) };
},
},
});- Set the Agent
targetResource selector andcustomerIdentityin the manifest. A public selector must positively match achannels.constal.ai/*label declared by the Agent. Central authentication maps provider evidence to accepted authority beforereceive. The same Auth Provider contract receives an exact{ kind, crn }ingress target for Channels and authenticated UIs; it is not a second UI authentication API. UseChannelContext.invoke()for declared external work; Channel and Auth Provider code never receives Credential bytes.
Verify
Send one invalid and one valid signed request to /v1/channels/:tenant/:namespace/:channel/*. Invalid proof must fail before receive; valid proof must resolve only an Agent matched by the Channel selector. Confirm the Run pins the Channel revision, selector hash, and selected Agent revision. Repeat the delivery id and confirm the recorded outcome is reused.
Next steps
Read Deploy a Channel, Deploy an Auth Provider, and Operate Channels for packaging, ingress, messages, and events.