Action functions
Build Action functions that your app, backend jobs, or agents can call on demand.
Action functions run when your app, backend job, or agent explicitly calls them. In SDK and API names, this function type is often called an action because it receives an input and returns an output.
Use action functions for reads, writes, multi-step provider workflows, unified API operations, and AI tools.
Tenklo provides a catalog of pre-built actions that you can call out of the box. This guide describes writing and deploying your own action function. To customize actions from the catalog, see Extend a template.
Create the function
Add a file under the integration's actions/ folder:
import { createAction } from 'nango';
import * as z from 'zod';
export default createAction({
description: 'Creates a GitHub issue',
version: '1.0.0',
input: z.object({
owner: z.string(),
repo: z.string(),
title: z.string(),
body: z.string().optional()
}),
output: z.object({
id: z.number(),
url: z.string().url()
}),
exec: async (nango, input) => {
const response = await nango.post({
endpoint: `/repos/${input.owner}/${input.repo}/issues`,
data: {
title: input.title,
body: input.body
}
});
return {
id: response.data.id,
url: response.data.html_url
};
}
});Import it from index.ts:
import './github/actions/create-issue';The output of an action function cannot exceed 2 MB. Return only the fields your app needs. For larger payloads, use the requests proxy to fetch data directly from your app.
For agents
Before generating an action function, collect the integration ID, connection ID for testing, provider endpoint, required input fields, expected output shape, and whether the operation is safe to retry.
Prefer explicit Zod schemas and short provider response mapping. If the action performs writes, make the logic idempotent before using async execution or retries.
Test and deploy
Dry run the function with realistic input:
nango dryrun create-issue '<CONNECTION-ID>' -e dev --input '{"owner":"NangoHQ","repo":"interactive-demo","title":"Bug report","body":"Created from a Nango action"}'Deploy your functions:
nango deployTo deploy only this action function:
nango deploy --action create-issue devFor broader test coverage, see the testing guide. To deploy from CI, see CI/CD.
Trigger synchronously
Synchronous execution is the default. The API or SDK call returns the function output.
import { Nango } from '@nangohq/node';
const nango = new Nango({ apiKey: process.env.NANGO_API_KEY! });
const result = await nango.triggerAction(
'github',
'<CONNECTION-ID>',
'create-issue',
{
owner: 'NangoHQ',
repo: 'interactive-demo',
title: 'Bug report',
body: 'Created from a Nango action'
}
);Trigger asynchronously
Use async execution for bulk writes, bursty work, or provider endpoints with tight rate limits. Tenklo queues the execution, applies retries, and lets you poll or receive a webhook when it completes.
Execution timing for asynchronous actions is not guaranteed. Async actions are currently processed sequentially per environment, so completion time depends on how many actions are queued and how long each one runs. Design callers to handle delays by polling the result endpoint or listening for the completion webhook.
const { id, statusUrl } = await nango.triggerActionAsync(
'github',
'<CONNECTION-ID>',
'create-issue',
{
owner: 'NangoHQ',
repo: 'interactive-demo',
title: 'Bug report',
body: 'Created from an async Nango action'
}
);Poll the result:
const result = await nango.getAsyncActionResult({ id });The async trigger response includes a statusUrl and id. Poll GET /action/<ACTION-ID> for the result: 404 means the execution is still running, 200 returns the function output, and 500 returns the execution error.
To receive completion events instead of polling, configure webhooks from Tenklo to your app and enable the Async action completed webhook.
Use retries only for idempotent function logic. Retried writes can otherwise create duplicate side effects in the external API.