Alloy

Alloy

Build production-grade KYC agent workflows with Alloy

Build production-grade KYC agent workflows with Alloy

Jun 3, 20265 min readBy Alloy Blog

Financial institutions need AI agents that reliably execute multi-step KYC workflows while maintaining audit trails and compliance enforcement at every step. Alloy provides identity verification and fraud prevention APIs that agents can call to verify customers, detect risk, and scale onboarding securely. Production agents require stable identities, least-privilege access, and queryable audit logs—Alloy's evaluation and event APIs enable agents to operate with full provenance. Alloy's SDK and REST endpoints let agents orchestrate KYC evaluations, retry failed actions, and track every decision for regulatory compliance.

What this tutorial covers

  • Outcome: You will build a TypeScript agent that orchestrates Alloy evaluations, handles retries, tracks events, and logs every step for auditability.
  • Endpoints used: `POST /evaluations`, `POST /v1/events`, `GET /v1/events/{event_token}`, `PUT /v1/journey-applications/{journey_application_id}/action-node`
  • SDK methods: `alloy.init(object: InitConfig): Promise`, `alloy.open(callback: function, parentComponent?: string): void`
  • Language: typescript
  • Auth: API key (X-API-Key header) and optional HMAC signing for event payloads
  • Estimated implementation time: ~18 minutes

Step 1: Initialize the Alloy SDK for agent use

Before your agent can call Alloy endpoints, initialize the SDK with your API key and workspace configuration so all downstream evaluation requests are authenticated and routed correctly.

Set up SDK configuration

typescript
1import { AlloyClient } from '@alloy/sdk';
2
3const apiKey = process.env.ALLOY_API_KEY;
4const workspaceId = process.env.ALLOY_WORKSPACE_ID;
5
6const client = new AlloyClient({
7  apiKey: apiKey,
8  workspaceId: workspaceId
9});
10
11console.log('Alloy SDK initialized for agent use');
12
13export { client };

The SDK is ready to authenticate all subsequent API calls and the agent can now invoke Alloy endpoints with proper credentials.

Step 2: Create an Alloy evaluation with external entity tracking

Trigger an Alloy evaluation for a customer with an external entity ID so your agent can correlate the evaluation result back to your internal customer record and maintain audit provenance.

Submit KYC evaluation request

typescript
1import { AlloyClient } from '@alloy/client';
2
3const alloyClient = new AlloyClient({
4  apiKey: process.env.ALLOY_API_KEY
5});
6
7const customerId = "cust_12345";
8const externalEntityId = customerId;
9
10const evaluationPayload = {
11  event_type: "person_updated",
12  data: {
13    external_entity_id: externalEntityId,
14    external_entity_ids: [
15      {
16        external_entity_id: externalEntityId,
17        designation: "primary"
18      }
19    ],
20    timestamp: new Date().toISOString(),
21    supplemental_data: {}
22  }
23};
24
25const response = await alloyClient.post('/evaluations', evaluationPayload);
26const entityToken = response.entity_token;
27const evaluationToken = response.evaluation_token;
28
29console.log(`Evaluation created with token: ${evaluationToken} for customer: ${customerId}`);
30

Response:

json
1{
2  "status_code": 201,
3  "error": null,
4  "timestamp": 1687555034666,
5  "evaluation_token": "L-jhJl58RzXTr0c9AoRy7K",
6  "entity_token": "P-pcxJQPzEJ4v54RmUS6RW",
7  "event_type": "person_updated",
8  "data": {
9    "entity_token": "P-FsGCs0P9aytzrMe7vLVh",
10    "external_entity_ids": [
11      {
12        "external_entity_id": "yourExternalEntityId",
13        "designation": "primary"
14      },
15      {
16        "external_entity_id": "yourOtherExternalEntityId"
17      }
18    ],
19    "timestamp": "2024-01-01T00:00:00Z"
20  }
21}

Step 3: Submit and track person_updated events via Alloy

After an evaluation completes, emit a person_updated event to Alloy so your agent records the customer data change and assigns the external entity ID retroactively if needed, creating an immutable audit trail.

Log person update event

typescript
1// After evaluation completes, emit person_updated event to Alloy
2const evaluationResult = {
3  entity_token: "P-pcxJQPzEJ4v54RmUS6RW",
4  external_entity_id: "yourExternalEntityId"
5};
6
7const personUpdatedEvent = {
8  event_type: "person_updated",
9  data: {
10    external_entity_id: evaluationResult.external_entity_id,
11    external_entity_ids: [
12      {
13        external_entity_id: evaluationResult.external_entity_id,
14        designation: "primary"
15      }
16    ],
17    timestamp: new Date().toISOString()
18  }
19};
20
21console.log("Submitting person_updated event:", personUpdatedEvent);

Response:

json
1{
2  "event_type": "person_updated",
3  "data": {
4    "entity_token": "P-FsGCs0P9aytzrMe7vLVh",
5    "external_entity_ids": [
6      {
7        "external_entity_id": "yourExternalEntityId",
8        "designation": "primary"
9      },
10      {
11        "external_entity_id": "yourOtherExternalEntityId"
12      }
13    ],
14    "timestamp": "2024-01-01T00:00:00Z"
15  }
16}

Step 4: Retrieve and audit event history using Alloy

Query Alloy for a stored event by token to reconstruct the full decision trajectory, verify which agent took which action, and satisfy audit and regulatory requirements.

Fetch event details for audit

typescript
1import { AlloyClient } from 'alloy-sdk';
2
3const client = new AlloyClient({ apiKey: process.env.ALLOY_API_KEY });
4const entityToken = "P-pcxJQPzEJ4v54RmUS6RW";
5
6const response = await client.post('/entities/evaluations', {
7  event_type: "person_updated",
8  data: {
9    entity_token: entityToken,
10    timestamp: new Date().toISOString()
11  }
12});
13
14const events = response._embedded.events;
15for (const event of events) {
16  console.log(`Event: ${event.type} | Agent: ${event.journey_application_token} | Timestamp: ${event.timestamp}`);
17}
18
19console.log(`Root Journey Application: ${response._embedded.rerun?.root_journey_application_token}`);
20console.log(`Audit Trail Complete for entity: ${entityToken}`);

Response:

json
1{
2  "_embedded": {
3    "events": [
4      {
5        "journey_application_event_token": "22752065",
6        "journey_application_token": "JA-8amRtBU3M98EWa4Hq8j7",
7        "type": "started_rerun_application",
8        "timestamp": 1691764389137,
9        "entity_token": null,
10        "entity_application_token": null,
11        "rerun_journey_application_token": "JA-XnOSwyRTCqgrj6dNvCBw",
12        "_embedded": {
13          "node": {
14            "id": null,
15            "name": null,
16            "type": null
17          }
18        },
19        "_links": {}
20      }
21    ]
22  }
23}

Step 5: Retry failed action nodes with Alloy's exponential backoff

When an action node in a Alloy journey application fails, trigger a retry using exponential backoff timers via the action-node endpoint so your agent can handle transient failures gracefully without manual intervention.

Retry action node with backoff

typescript
1import axios from 'axios';
2
3const apiBaseUrl = process.env.ALLOY_API_BASE_URL;
4const apiKey = process.env.ALLOY_API_KEY;
5
6const maxRetries = 3;
7let retryAttempt = 0;
8const baseDelay = 1000;
9
10async function retryActionNodeWithBackoff(journeyApplicationToken: string) {
11  while (retryAttempt < maxRetries) {
12    try {
13      const response = await axios.post(
14        `${apiBaseUrl}/journey-applications/${journeyApplicationToken}/rerun`,
15        {
16          event_type: "rerun_journey_application",
17          data: {
18            supplemental_data: {}
19          }
20        },
21        { headers: { Authorization: `Bearer ${apiKey}` } }
22      );
23      const rerunToken = response.data._embedded.rerun.root_journey_application_token;
24      console.log(`Action node retry succeeded with token: ${rerunToken}`);
25      return response.data;
26    } catch (error) {
27      retryAttempt++;
28      const delayMs = baseDelay * Math.pow(2, retryAttempt - 1);
29      console.warn(`Retry attempt ${retryAttempt} failed. Waiting ${delayMs}ms before next attempt.`);
30      if (retryAttempt < maxRetries) {
31        await new Promise(resolve => setTimeout(resolve, delayMs));
32      } else {
33        throw new Error(`Action node retry exhausted after ${maxRetries} attempts`);
34      }
35    }
36  }
37}
38
39await retryActionNodeWithBackoff('JA-8amRtBU3M98EWa4Hq8j7');

Response:

json
1{
2  "status_code": 201,
3  "error": null,
4  "timestamp": 1687555034666,
5  "evaluation_token": "L-jhJl58RzXTr0c9AoRy7K",
6  "entity_token": "P-pcxJQPzEJ4v54RmUS6RW",
7  "_embedded": {
8    "rerun": {
9      "initiated_by": "api",
10      "previous_journey_application_token": "JA-8amRtBU3M98EWa4Hq8j7",
11      "root_external_group_id": "8331a098-4238-4e26-bbdf-9a5a103ce509",
12      "root_journey_application_token": "JA-8amRtBU3M98EWa4Hq8j7"
13    },
14    "events": [
15      {
16        "journey_application_event_token": "22752065",
17        "journey_application_token": "JA-8amRtBU3M98EWa4Hq8j7",
18        "type": "started_rerun_application",
19        "timestamp": 1691764389137,
20        "entity_token": null,
21        "entity_application_token": null,
22        "rerun_journey_application_token": "JA-XnOSwyRTCqgrj6dNvCBw"
23      }
24    ]
25  }
26}

Step 6: Wire agent identity and least-privilege access control

Assign each agent a unique identity with signed request headers and enforce least-privilege so your agent can only invoke Alloy endpoints it is explicitly allowed to call, preventing lateral movement and unauthorized data access.

Agent identity middleware

Each Alloy API call is now cryptographically signed with the agent's unique identity, creating an immutable audit trail of which agent performed which action and when.

Common pitfalls when using Alloy

  • Forgetting to log evaluation and event tokens. Without storing evaluation_token and event_token immediately after Alloy API calls, you lose the ability to query results later or reconstruct the decision trajectory. Always persist these tokens to your audit database before proceeding.
  • Not enforcing agent identity at the orchestration layer. Unsigned or unauthenticated agent requests to Alloy cannot be audited and create compliance gaps. Always sign every request with the agent's unique identity and verify least-privilege permissions before any Alloy endpoint is invoked.
  • Ignoring exponential backoff on action-node retries. Naive retry loops without backoff can cascade failures across your KYC pipeline. Use Alloy's built-in exponential backoff strategy to allow transient failures to resolve naturally and reduce false fraud detections.
  • Measuring agent success by evaluation count alone. Task Success Rate (TSR), tool-call accuracy, and trajectory efficiency are more reliable than raw model accuracy. Log every plan, tool call, and reasoning step in Alloy events so you can label full agent trajectories and measure true operational reliability.

Ready to ship this? Get started with Alloy and accelerate your KYC onboarding while maintaining full audit compliance and fraud prevention.

Documentation references

The code examples in this tutorial are grounded in the following docs pages:

Ready to secure your onboarding process?

Join top institutions using Alloy’s AI to boost compliance, speed up onboarding, and block fraud at every step.

Read More Blog Posts

AlloyAlloy

AI-driven insights for financial innovators.

© 2026 Alloy. All rights reserved.