Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.svantic.com/llms.txt

Use this file to discover all available pages before exploring further.

Securing dispatches

Hosted-mode agents serve A2A on a public URL — if anyone learns the URL, they can POST to it. Dispatch auth is the SDK’s answer: Svantic attaches a signed envelope to every dispatch, and the SDK verifies it before your handler runs. Requests without a valid envelope are rejected. Connected-mode agents get transport-level trust from the authenticated WebSocket; dispatch auth is still accepted but optional. This guide is the operator’s view. For the full verifier API, see Dispatch auth reference.

Pick a scheme

SchemeHow it worksUse when
svantic_jwtSvantic signs an HS256 JWT with a shared secret. Claims include tenant_id, agent_type, instance_id, dispatch_id, and exp.Default choice. Gives you audit claims for free.
shared_secretSvantic attaches an opaque token you’ve also configured on the agent. Constant-time comparison on the agent side.You can’t hold a per-agent secret, or you want the simplest possible verification.
Both are safe; svantic_jwt is richer. Most agents want it.

Turn it on

Step 1 — generate a secret

openssl rand -base64 48

Step 2 — store it in the Svantic dashboard

Settings → Dispatch Auth → [your agent] → Rotate secret. Paste the value. Svantic will start signing envelopes to this agent with it.

Step 3 — configure the SDK

import { MeshConnector } from '@svantic/sdk/mesh';

const mesh = new MeshConnector(agent, {
  client_id: process.env.SVANTIC_CLIENT_ID!,
  client_secret: process.env.SVANTIC_CLIENT_SECRET!,
  dispatch_auth: {
    scheme: 'svantic_jwt',
    required: true,
  },
});
dispatch_auth is part of MeshConnectorConfig. It can also be set via AttachConfig.mesh.dispatch_auth.

Step 4 — make the secret available to the agent

The SDK reads the verifier config from your VerifierConfig:
import { verify_dispatch_auth, DispatchAuthVerifyError } from '@svantic/sdk';

const VERIFIER_CONFIG = {
  instance_id: agent.instance_id,
  signing_secret: process.env.SVANTIC_DISPATCH_SECRET!,
  clock_skew_s: 5,
};
Store SVANTIC_DISPATCH_SECRET the same way you store any other secret — never commit it, never bake it into images.

Verify inside a handler

Until dispatch-auth wiring is turned on in the executor by default, call the verifier from handlers where the check matters:
import { verify_dispatch_auth, DispatchAuthVerifyError } from '@svantic/sdk';

agent.define_capability({
  name: 'publish_release',
  description: 'Ship a release.',
  parameters: { /* … */ },
  handler: async (args, ctx) => {
    try {
      const authed = verify_dispatch_auth(args as any, VERIFIER_CONFIG);
      if (authed.tenant_id !== ctx.tenant_id) {
        throw new Error('tenant_mismatch');
      }
    } catch (err) {
      if (err instanceof DispatchAuthVerifyError) {
        throw new Error(`Unauthorized: ${err.code}`);
      }
      throw err;
    }

    // … safe to proceed
  },
});
Branch on err.code when you need to distinguish “missing envelope” from “expired” in logs or metrics.

Rotating the secret

  1. In the dashboard, add a new secret alongside the old one. Svantic continues to sign with the old one while the new one propagates.
  2. Deploy the agent with both secrets trusted (use shared_secrets map with multiple entries keyed by credentials_ref, or deploy two instances in parallel).
  3. Cut the dashboard to sign with the new secret.
  4. Once no envelopes signed with the old secret are still in flight (wait at least twice the envelope TTL), remove the old secret from the agent.

Choosing between shared_secret and svantic_jwt

  • shared_secret verification is a constant-time string compare. No library dependency on the verifier side, no key format concerns.
  • svantic_jwt carries tenant / agent / dispatch claims you can log or enforce on (per the DispatchAuthContext), and exp is checked for you.
Pick svantic_jwt unless you have a specific reason not to.

Connected-mode agents

Connected agents authenticate the transport (the WebSocket is opened with your agent credentials), so every dispatch is already attributable. Dispatch auth is still accepted — treat it as defense in depth. Turn it on in hosted mode first.

See also