Skip to main content
Version: PromptQL

Lambda Connector Basics

Introduction

You can use lambda connectors to give PromptQL abilities to execute custom business logic on behalf of the user. We can add a lamdba connector runtime in Node.js with TypeScript, Python, or Go, and expose functions to PromptQL as tools it can use. This means PromptQL isn't limited to querying data — it can trigger logic, run workflows, or transform inputs into actions, all within a secure and consistent API environment.

By treating logic like a first-class data source, PromptQL ensures your application has a unified surface for interacting with databases, API services, and whatever actions you want your application to be able to take. You define how the system should respond to user queries, apply business rules, or even call third-party APIs.

Initialize a lambda connector

Initialize a new connector in a project directory:
ddn connector init your_name_for_the_connector -i

Choose the lambda connector to correspond with the language you'd like to use for your functions.

When you add the hasura/nodejs connector, the CLI will generate a Node.js package with a functions.ts file. This file is the entrypoint for your connector.

As this is a Node.js project, you can easily add any dependencies you desire by running npm i <package-name> from this connector's directory.

Write a function

There are two types of lambdas you can write, functions and procedures.

  • Functions are read-only. Queries without side effects. PromptQL will not ask for confirmation before calling them.
  • Procedures can mutate data and have side effects. PromptQL will ask for confirmation before calling them.

Examples

The following examples show how to create basic lambda functions in each language. You can replace the contents of the functions.ts, functions.py, or any .go file in the /functions directory of the Go connector with the following examples.

<subgraph-name>/connector/<connector-name>/functions.ts
/**
* Takes an optional name parameter and returns a friendly greeting string
* @param {string} [name] - Optional name to personalize the greeting
* @returns {string} A greeting in the format "hello {name}" or "hello world" if no name provided
* @readonly
*/
export function hello(name?: string) {
return `hello ${name ?? "world"}`;
}

The JSDoc comments are optional, but the first general comment is highly recommended to help PromptQL understand the function's purpose and parameters and will be added to the function's metadata.

The @readonly tag indicates that the function does not modify any data, and PromptQL will be able to call this without asking for confirmation. Under the hood, DDN will create an NDC function for @readonly lambdas and an NDC procedure for functions that are not marked as @readonly.

Exposing your lambda functions

Once you've created your lambda functions, you need to expose them to PromptQL by generating metadata for them.

Step 1. Introspect the connector and add the metadata

ddn connector introspect <connector-name>
List the commands discovered during introspection:
ddn connector show-resources <connector-name>

You should see the command being AVAILABLE which means that there's not yet metadata representing it.

ddn commands add <connector-name> <command-name>
Add semantic metadata

If you did not add comments to your function, we highly recommend adding a description to the command object added above.

PromptQL's performance is improved by providing more context; if you guide its understanding of what a particular function does and how it should be called, you'll get better results and fewer errors.

Step 2. Create and run a new build and test the function

Create a new local build:
ddn supergraph build local
Run your services:
ddn run docker-start
In a new terminal tab, open the devlopment console:
ddn console --local

Head over to the PromptQL Playground and ask PromptQL to call your lambda function.

say hello to everyone

Retrieve information

You can add a lambda function which reaches out to external APIs to retrieve data which PromptQL can use.

Step 1. Call an external API

Open the app/connector/typescript/functions.ts file.

Replace the contents with the following:
/**
* Calls httpbin.org API to create a personalized greeting for the given name. Takes an optional name parameter and returns a friendly greeting string.
* @param {string} [name] - Optional name to personalize the greeting
* @returns {Promise<{ greeting?: string }>} A Promise resolving to an object containing the optional greeting message
* @readonly
*/
export async function helloFromHttpBin(name?: string): Promise<{ greeting?: string }> {
const greeting = { greeting: name };

const response = await fetch("https://httpbin.org/post", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ greeting: `Hello ${name}!` }),
});

const data: any = await response.json();
return { greeting: data?.json?.greeting };
}

Remember to expose your lambda functions to PromptQL by following the steps in Exposing your lambda functions.

Take action

You can use lambda connectors to add custom business logic to your application that takes action on behalf of a user.

Step 1. Add custom logic

Replace the contents of functions.ts with the following:
/*
* Interface for the response when taking action on behalf of a user.
* Contains success status and message.
*/
interface UserActionResponse {
success: boolean;
message: string;
}

/*
* This function simulates taking an action on behalf of a user. It logs the request made by the user
* and returns a response object indicating the success status and a message.
*
* @param {string} request - What the user wants to do
* @returns {UserActionResponse} - The response object containing success status and message
*/
export function takeActionOnBehalfOfUser(request: string): UserActionResponse {
// In a real application, you'd replace this with your custom business logic.
// You could update data in a database or use an API to update another service.
console.log(`Taking action on behalf of user: ${request}`);
return {
success: true,
message: `Successfully took action on user's behalf: ${request}`,
};
}

The absence of the @readonly tag indicates that this function will modify data. PromptQL will ask for confirmation before calling it.

Remember to expose your lambda functions to PromptQL by following the steps in Exposing your lambda functions.

Take action on behalf of user
What about custom native operations?

Many complex reads and writes to your data sources can be accomplished with custom native queries and mutations. Check out the connector-specific reference docs for generating queries and mutations using the native capabilities of your data source.