Skip to main content

How to create an AI-based action?

AI-powered actions can enhance your apps by automatically generating content, analyzing data, or providing intelligent suggestions. This is particularly useful when you need to create dynamic content based on existing data without manual intervention.

This guide shows you how to create an action that uses OpenAI to generate compelling product descriptions automatically based on product names.

Overview

The process involves:

  1. defining an AI prompt with clear instructions
  2. making a request to OpenAI API
  3. processing the response
  4. updating the record with generated content

Prerequisites

Before implementing this action, ensure you have:

  • an OpenAI API key
  • the API key stored as COMIND_OPEN_AI_API_KEY in your app secrets
  • a text field for product name (e.g., title)
  • a rich text field for the description (e.g., description)

Implementation

In your actions/logic/index.ts file, add the following action function and export it. You can either create a new action called generate_description or add this code to an existing action:

// actions/index.ts
import type { AppActionArray } from "@comind/api";
const actions = [
{
caption: "Generate description",
options: {
showAsButton: true,
viewMode: "local",
},
uid: "generate_description",
},
] as const satisfies AppActionArray;

export default actions;
// actions/logic/index.ts

export default {
generate_description,
// ... other actions
} satisfies ActionLogic<typeof entity>;

import { entity } from "#typings";
import { RestApi, AppSchema } from "@comind/api/server";

const prompt = `
Generate a compelling product description for provided product name in exactly 3 paragraphs.
Use minimal HTML formatting only (bold tags for emphasis, bullet points if needed).
Each paragraph should be put into <p></p> tags. Format as bold 1-2 most important words.
Focus on key features, benefits, and target audience. Keep it professional and engaging.`;

function generate_description() {
const response = getOpenAiResponse(prompt, entity.title || "");
setDescription(response);
}

function setDescription(response: any) {
if (!response.Data.output) throw JSON.stringify(response);
const outputWithMessage = response.Data.output.find(
(o: any) => o.type === "message"
);
const outputText = outputWithMessage.content[0].text;
entity.description = outputText;
}

function getOpenAiResponse(
instructions: string,
input: string,
model = "gpt-5-nano"
) {
const { COMIND_OPEN_AI_API_KEY } = AppSchema.getSecrets();
if (!COMIND_OPEN_AI_API_KEY) throw "Can't find COMIND_OPEN_AI_API_KEY";

const url = "https://api.openai.com/v1/responses";
const body = {
input,
instructions,
max_output_tokens: 20000,
model,
reasoning: { effort: "minimal" },
};

RestApi.createClient(url);
RestApi.createRequest("", "POST");
RestApi.addHeader("Authorization", `Bearer ${COMIND_OPEN_AI_API_KEY}`);
RestApi.addHeader("Content-Type", "application/json");
RestApi.addJsonBody(body);
const response = RestApi.executeRequest();

entity.c_json_response = JSON.stringify(response);

return response;
}

How it works

  1. Prompt definition: the prompt constant contains detailed instructions for the AI. It specifies:

    • the output format (3 paragraphs)
    • HTML formatting rules (minimal, with <p> tags)
    • content requirements (features, benefits, target audience)
    • style guidelines (professional and engaging)
  2. API key retrieval: the action retrieves the API key from app secrets using AppSchema.getSecrets(). This ensures sensitive credentials are not hardcoded in your code.

  3. API request: the getOpenAiResponse() function:

    • creates a REST client pointing to OpenAI's API
    • sets required headers (Authorization and Content-Type)
    • sends a POST request with the prompt and input data
    • stores the raw JSON response in c_json_response field for debugging
  4. Response processing: the setDescription() function:

    • validates that the response contains output data
    • finds the message-type output from the response
    • extracts the text content
    • updates the description field with the generated text
  5. Main action: the generate_description() function orchestrates the process by calling the helper functions in sequence.

Setting up the API key

To configure your OpenAI API key:

  1. navigate to your app's configuration
  2. go to the secrets management section
  3. add a new secret named COMIND_OPEN_AI_API_KEY
  4. paste your OpenAI API key as the value
tip

Keep your API keys secure and never commit them to version control. Always use the secrets management system.

Field requirements

For this action to work, ensure your app has:

  • a text field named title (for the product name)
  • a rich text field named description (for the generated content)
  • optionally, a text field named c_json_response for storing raw API responses (useful for debugging)

Error handling

The action includes error handling for common scenarios:

  • Missing API key: throws an error if COMIND_OPEN_AI_API_KEY is not configured
  • Invalid response: throws an error with response details if the expected output structure is missing
  • API failures: REST API errors will be thrown automatically

Customization options

You can customize this action by:

  • Changing the prompt: modify the prompt constant to generate different types of content (e.g., marketing copy, technical specifications, social media posts)
  • Using different models: change the model parameter in getOpenAiResponse() to use different AI models (e.g., gpt-5, gpt-5-mini)
  • Adjusting token limits: modify max_output_tokens to control the length of generated content
  • Different input sources: instead of entity.title, use other fields or combine multiple fields as input
  • Custom formatting: modify the prompt to request different HTML formatting or plain text output
  • Multiple languages: enhance the prompt to generate content in specific languages

Example usage

  1. create a new product record
  2. enter the product name in the title field (e.g., "Wireless Noise-Canceling Headphones")
  3. click the "Generate Description" action button
  4. the AI will generate a professional product description and populate the description field

Example output:

<p>
Introducing our <b>premium wireless headphones</b> that combine cutting-edge
noise-canceling technology with exceptional audio quality.
</p>

<p>
These headphones feature adaptive noise cancellation that automatically
adjusts to your environment, delivering crystal-clear sound whether you're in
a busy office or traveling. The <b>40-hour battery life</b> ensures
uninterrupted listening throughout your entire workweek.
</p>

<p>
Perfect for professionals, commuters, and audio enthusiasts who demand
superior sound quality and comfort during extended listening sessions.
</p>

Use cases

This AI-based action approach is particularly useful for:

  • E-commerce: automatically generating product descriptions from product names and attributes
  • Content management: creating initial drafts for articles, blog posts, or documentation
  • Data enrichment: adding descriptive content to catalog items
  • Multilingual content: generating translations or localized versions of text
  • Summarization: creating executive summaries from detailed reports
  • Research-enhanced content: combining web search results with AI to create more accurate and informed descriptions
  • Competitive analysis: generating product positioning based on real-time market research

Advanced scenarios

Generating content from multiple fields

You can combine multiple fields as input:

function generate_description() {
const input = `
Product name: ${entity.title}
Category: ${entity.category}
Key features: ${entity.features}
Price range: ${entity.price_range}
`;
const response = getOpenAiResponse(prompt, input);
setDescription(response);
}

Using different AI models for different purposes

function generate_short_description() {
// Use faster, cheaper model for short content
const response = getOpenAiResponse(shortPrompt, entity.title, "gpt-5-nano");
entity.short_description = processResponse(response);
}

function generate_detailed_analysis() {
// Use more powerful model for complex analysis
const response = getOpenAiResponse(detailedPrompt, entity.data, "gpt-5");
entity.analysis = processResponse(response);
}

Conditional generation

function generate_description() {
// Only generate if description is empty
if (entity.description) {
throw "Description already exists. Clear it first if you want to regenerate.";
}

const response = getOpenAiResponse(prompt, entity.title || "");
setDescription(response);
}

Cost considerations

Keep in mind that AI API calls incur costs:

  • monitor your API usage through OpenAI's dashboard
  • consider implementing rate limiting for high-volume scenarios
  • use smaller models (like gpt-5-nano) when appropriate
  • cache generated content to avoid regenerating the same content multiple times
  • set appropriate max_output_tokens limits to control costs

Debugging

The action stores the raw API response in entity.c_json_response, which is helpful for:

  • inspecting the full response structure
  • debugging issues with response parsing
  • analyzing API performance and token usage
  • troubleshooting unexpected outputs

To view the raw response, add c_json_response field to your layout during development.

Video demonstration