When Step Functions invokes Lambda via the AWS SDK integration
("arn:aws:states:::lambda:invoke"), the event received by the Lambda handler
is an object that wraps the original input under a Payload
key. The Payload
is already parsed JSON.
SMOZ’s base event map includes a first‑class step
token that reflects this:
// Conceptual shape (Zod v4):
z.object({ Payload: z.unknown().optional() }).catchall(z.unknown());
Notes:
.passthrough()
. Use .catchall(z.unknown())
to allow
additional properties (e.g., StatusCode
, ExecutedVersion
) while keeping a
typed Payload
key.step
token
covers the common “Lambda Invoke” pattern.// app/functions/step/exampleTask/lambda.ts
import { z } from 'zod';
import { app, APP_ROOT_ABS } from '@/app/config/app.config';
import { join } from 'node:path';
// Validate only the part you use; here we expect an object payload.
export const eventSchema = z.object({
Payload: z.object({ foo: z.string() }).optional(),
});
export const responseSchema = z.void(); // or z.any().optional()
export const fn = app.defineFunction({
functionName: 'exampleTask',
eventType: 'step', // non‑HTTP
eventSchema,
responseSchema,
callerModuleUrl: import.meta.url,
endpointsRootAbs: join(APP_ROOT_ABS, 'functions', 'step').replace(/\\/g, '/'),
});
// app/functions/step/exampleTask/handler.ts
import { fn } from './lambda';
export const handler = fn.handler(async (event) => {
// The wrapper event may include Payload; validate its structure as needed.
const payload = (event as { Payload?: unknown }).Payload as
| { foo?: string }
| undefined;
// ... do work ...
});
catchall(z.unknown())
with a tighter schema or a pipeline that drops/normalizes
unexpected properties before the handler runs.z.record
on the nested Payload.catchall
maps well to OpenAPI’s additionalProperties
pattern.