Voyage Agent Layer
Use this skill when an agent needs to provision API credentials, create or publish a journey, or build a custom registration portal against Voyage.
Guardrails
- Do not use real customer tenants for experiments.
- Do not print, store in docs, or commit API-key secrets. Use
placeholders such as
vyg_live_xxx. - API keys cannot mint other keys. API-client administration requires a live identity session cookie for a tenant owner/admin or platform admin.
- Current admin journey routes require
journey.build; do not assumejourney.readis enough for/v1/journeys. - Public journey registration routes are public so browser flows can
submit. Server-side agents should still send a key with
registration.write.
Required Inputs
Collect or infer:
apiBaseUrl: edge gateway URL.identityBaseUrl: identity worker URL for API-client admin.tenantSlug.- Admin session cookie, only when minting a client/key.
- Target event ID for registration-backed journeys.
- Journey type:
appointment,event, orqueue. - Registration portal host/runtime choice.
Credential Workflow
- Create an API client:
curl -sS \
-X POST "$IDENTITY_BASE_URL/t/$TENANT_SLUG/admin/api-clients" \
-H "content-type: application/json" \
-H "cookie: identity_session=..." \
--data '{"name":"Agent journey builder","description":"Journey and registration portal automation"}'- Mint a key:
curl -sS \
-X POST "$IDENTITY_BASE_URL/t/$TENANT_SLUG/admin/api-clients/client_xxx/keys" \
-H "content-type: application/json" \
-H "cookie: identity_session=..." \
--data '{"scopes":["journey.build","registration.write"]}'Store the one-time
secretin the agent runtime secret manager asVOYAGE_API_KEY.For rotation, call:
curl -sS \
-X POST "$IDENTITY_BASE_URL/t/$TENANT_SLUG/admin/api-clients/client_xxx/keys/key_xxx/rotate" \
-H "content-type: application/json" \
-H "cookie: identity_session=..." \
--data '{"scopes":["journey.build","registration.write"]}'Journey Build Workflow
Use @voyage/sdk and
@voyage/journey-runtime/core.
import { createVoyageClient } from "@voyage/sdk";
import { defaultJourneyConfig } from "@voyage/journey-runtime/core";
const voyage = createVoyageClient({
baseUrl: process.env.VOYAGE_API_BASE_URL ?? "https://api.example.com",
tenantSlug: process.env.VOYAGE_TENANT_SLUG ?? "acme-events",
apiKey: process.env.VOYAGE_API_KEY ?? "vyg_live_xxx",
});
const config = defaultJourneyConfig("event");
const draft = await voyage.journeys.create({
type: "event",
slug: "private-preview",
eventId: "evt_123",
config: {
...config,
name: "Private preview",
_eventId: "evt_123",
},
});
const live = await voyage.journeys.publish(draft.journeyId, {
version: draft.version,
publishTargets: draft.configJson.publishTargets,
});Registration Portal Workflow
Backend prerequisites:
- Tenant is active and resolvable by path or domain.
- Tenant config DB has
feature_catalog.feature_key = 'journey_builder'for admin journey build calls. - Tenant ops DB has an
events_studio_eventsrow for the target event. - The journey row has
eventIdor config_eventIdset to that event ID.
Portal server action:
const result = await voyage.journeys.submitPublicRegistration("private-preview", {
selectedTickets: [{ tierId: "general", quantity: 1 }],
guest: {
firstName: form.firstName,
lastName: form.lastName,
email: form.email,
phone: form.phone,
},
answers: form.answers,
agreedToTerms: true,
surfaceType: "journey",
});
const confirmed = await voyage.journeys.getPublicRegistration(
"private-preview",
result.registration.guestId,
result.registration.email,
);Do not put VOYAGE_API_KEY in browser JavaScript. The
portal browser posts to the portal backend; the backend calls
Voyage.
Data Structures To Expect
The registration path writes and updates these tenant ops tables:
events_studio_guests: one row per captured registration.events_studio_events: registration and attendance counts are refreshed after writes.events_studio_page_visits: optional visit tracking through/visit.
The journey path writes:
journey_surfaces: draft/live versions.journey_staff_rosterandjourney_staff_booking_links: default staff links are inserted when missing.
Acceptance Check
Before telling a human a portal works:
- Publish the journey.
- Load the public journey by slug through the live host or intended API base.
- Submit a full registration through the portal backend.
- Read the registration back with
getPublicRegistration. - Confirm the returned event count increased or the row exists in tenant ops data.
Green typechecks or a rendered form are not enough.