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 & automations, all within a secure and consistent API environment.

By treating logic like a first-class data source, PromptQL ensures your application has a unified interface 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.
Return types

Lambda functions work best when you use a non-scalar return type as the added context of the shape of the type helps PromptQL understand how the function can and should be used. In the examples below, you'll see various interfaces, types, and structs used as the return types in these functions.

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
/**
* This interface represents the standard response returned by greeting or other playful functions.
*/
interface HelloResponse {
success: boolean;
message: string;
}

/**
* The hello() function takes in an optional name as a string and returns a HelloResponse object with a success boolean and greeting as the message's value.
* @param {string} name - An optional name to greet.
* @returns {HelloResponse} A HelloResponse object greeting the person.
* @readonly Exposes the function as an NDC function (the function should only query data without making modifications)
*/
export function hello(name?: string): HelloResponse {
return {
success: true,
message: `hello ${name ?? "world"}`,
};
}

/**
* The complimentPerson() function pretends to improve a person's day by giving them a compliment.
* @param {string} name - An optional name of the person to compliment.
* @returns {HelloResponse} A HelloResponse object with a positive message.
*/
export function complimentPerson(name?: string): HelloResponse {
return {
success: true,
message: `You're doing great today, ${name ?? "friend"}!`,
};
}

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, the connector will expose 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

Or, try your procedure and get a nice compliment (after approval of course!):

Give Rikin a compliment

Retrieve information

The examples above are great templates for learning how to use functions and procedures. A common use for functions is to reach out to external APIs to retrieve data which PromptQL can use. You can learn more about that below.

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.

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.