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, target Agent, 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:
ts
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 }, context) {
const proof = await context.invoke<{ valid: boolean; subject?: string }>(
context.resources.verifier!, "verify", { 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:
ts
import { authProviderName, channel, resourceName } 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"),
target: resourceName({ environment: "production", tenant: "acme", namespace: "default", kind: "agent", path: "support" }),
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
customerIdentityin the manifest torequired,optional, ornone. Central authentication maps provider evidence to accepted authority beforereceive. 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 produce the expected source, target, principal, and customer partition. 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, events, and alarms.