Skip to main content
INIT / INTEGRATIONS

Agent consumption golden path

Authenticate with a service client, discover providers, connect, validate, execute, and reconcile uncertain outcomes with the SDK or CLI.

Agent markdown

One golden path for coding agents and consumer backends. Start from discovery indexes, use environment-only credentials, then Connect, validate, execute, and reconcile. Provider-specific schemas live on generated pages—do not copy them into your agent prompt.

Canonical vs deployment-effective: /llms.txt and /api/catalog/v1/providers describe the public contract. Authenticated GET /v1/tenants/{tenant_id}/providers describes what this deployment and service-client policy allow.

This guide uses Slack as one example provider with redacted IDs. Swap the provider/action IDs after fetching the matching generated page (for example Slack actions or /md/integrations/slack/actions).

Sequence

  1. Environment-only authentication
  2. Auth status / doctor
  3. Tenant creation
  4. Provider and action discovery
  5. Connect-session creation and frontend handoff
  6. Status polling and connection test
  7. Local input validation
  8. Safe read and idempotent write execution
  9. ACTION_OUTCOME_UNKNOWN reconciliation

Related deep-dives: service-client auth, Connect lifecycle, action execution, execution reconciliation. CLI overview: fuse --help.

1. Environment-only authentication

Operators issue svc_live_* service-client keys. Consumer services and the CLI read the token only from the environment. Never pass a token as a CLI flag, URL query, or checked-in config.

export FUSE_API_URL="https://api.example.invalid"
export FUSE_DOCS_URL="https://docs.example.invalid"
export FUSE_TOKEN="[REDACTED]"

TypeScript SDK:

import { FuseClient } from "@init/fuse-sdk";

const token = process.env.FUSE_TOKEN;
if (token === undefined || token.length === 0) {
  throw new Error("Set FUSE_TOKEN");
}

const client = new FuseClient({
  baseUrl: process.env.FUSE_API_URL ?? "https://api.example.invalid",
  accessToken: token,
});

CLI: export FUSE_TOKEN, then run commands. Do not pass service credentials as command-line flags, URL query parameters, or checked-in config.

2. Auth status / doctor

Confirm the service-client profile before creating tenants or Connect sessions.

const profile = await client.getServiceClient();
// GET /v1/service-client — masked identity only; no key material
fuse auth status
fuse doctor \
  --origin "https://app.example.invalid" \
  --return-url "https://app.example.invalid/integrations/result"

doctor also checks docs reachability (including /llms.txt) without printing secrets.

3. Tenant creation

import { createIdempotencyKey } from "@init/fuse-sdk";

const tenant = await client.createTenant({
  externalId: "org_example",
  displayName: "Example Org",
  idempotencyKey: createIdempotencyKey("tenants-create"),
});
// tenant.id → ten_[REDACTED]
fuse tenants create \
  --external-id "org_example" \
  --display-name "Example Org"
# Persist tenant.id, then:
export FUSE_TENANT_ID="ten_[REDACTED]"

4. Provider and action discovery

Prefer the public catalog for exact schemas, then the authenticated API for deployment-effective availability.

const providers = await client.listProviders("ten_[REDACTED]");
const actions = await client.listActions("ten_[REDACTED]", "slack");
const channelsList = actions.actions.find((action) => action.id === "channels.list");
fuse providers list
fuse providers get slack
fuse actions list slack
fuse actions get slack channels.list

5. Connect-session creation and frontend handoff

Your backend creates the session. Hand the one-time Connect token to your frontend only—never log it to stderr, persist it for replay, or reuse the same idempotency key to recover it.

const session = await client.createConnectSession({
  tenantId: "ten_[REDACTED]",
  provider: "slack",
  authKind: "oauth2_authorization_code",
  allowedOrigin: "https://app.example.invalid",
  returnUrl: "https://app.example.invalid/integrations/result",
  requestedActions: ["channels.list", "messages.post"],
  idempotencyKey: createIdempotencyKey("connect-sessions-create"),
});
// session.id → cs_[REDACTED]
// session.token → one-time Connect token for the frontend only
fuse connect-sessions create \
  --provider slack \
  --origin "https://app.example.invalid" \
  --return-url "https://app.example.invalid/integrations/result" \
  --action channels.list \
  --action messages.post \
  --format json > /tmp/connect-session.json
# Restrict file permissions yourself. Do not echo the token into logs.

See connection lifecycle for OAuth vs static credential Connect behavior.

6. Status polling and connection test

Poll the non-secret Connect result, then test the durable connection.

const status = await client.getConnectSession("ten_[REDACTED]", "cs_[REDACTED]");
// When status is used, read connection_id → con_[REDACTED]

await client.testConnection({
  tenantId: "ten_[REDACTED]",
  connectionId: "con_[REDACTED]",
  idempotencyKey: createIdempotencyKey("connections-test"),
});
fuse connect-sessions wait cs_[REDACTED]
fuse connections test con_[REDACTED]

7. Local input validation

Validate against the deployment-effective inputSchema before dispatch. The CLI actions validate path never calls :execute.

import { validateAgainstJsonSchema } from "@init/fuse-contracts";

const listed = await client.listActions("ten_[REDACTED]", "slack");
const action = listed.actions.find((entry) => entry.id === "channels.list");
if (action === undefined) {
  throw new Error("channels.list is not enabled for this deployment");
}

const input = {};
validateAgainstJsonSchema(action.inputSchema, input);
fuse actions validate channels.list \
  --connection con_[REDACTED] \
  --input '{}'

8. Safe read and idempotent write execution

Reads do not need an idempotency key. Writes and destructive actions do. Prefer documented action IDs; full retry rules are in execute actions.

// Safe read
const channels = await client.executeAction({
  tenantId: "ten_[REDACTED]",
  connectionId: "con_[REDACTED]",
  actionId: "channels.list",
  input: {},
});

// Idempotent write
const posted = await client.executeAction({
  tenantId: "ten_[REDACTED]",
  connectionId: "con_[REDACTED]",
  actionId: "messages.post",
  input: {
    channel_id: "C[REDACTED]",
    text: "hello from the consumer service",
  },
  idempotencyKey: createIdempotencyKey("actions-execute"),
});
fuse actions execute channels.list \
  --connection con_[REDACTED] \
  --input '{}'

fuse actions execute messages.post \
  --connection con_[REDACTED] \
  --input '{"channel_id":"C[REDACTED]","text":"hello from the consumer service"}'

9. ACTION_OUTCOME_UNKNOWN reconciliation

When a write returns ACTION_OUTCOME_UNKNOWN, do not blindly retry with a new idempotency key. Inspect the execution record, then reconcile with the provider or your own records.

const executions = await client.listActionExecutions({
  tenantId: "ten_[REDACTED]",
  connectionId: "con_[REDACTED]",
  limit: 20,
});

const execution = await client.getActionExecution(
  "ten_[REDACTED]",
  "act_[REDACTED]",
);
// Inspect status, action_id, connection_id, and safe summaries — not raw provider secrets

REST equivalents:

  • GET /v1/tenants/{tenant_id}/action-executions
  • GET /v1/tenants/{tenant_id}/action-executions/{execution_id}

Reuse the same idempotency key and body only for transport-level retries of an in-flight write. After an unknown outcome, treat a new key as a new attempt.

CLI help

fuse --help
fuse actions --help
fuse connect-sessions --help

Where to go next