SkillAgentSearch skills...

Cigs

🚬 cigs are chainable Ai functions for typescript. Call functions with natural language and get a response back in a specified structure. Uses OpenAI's latest Structured Outputs.

Install / Use

/learn @longtail-labs/Cigs
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

🚬 cigs - Composable Ai functions for Typescript

GitHub top language JSR Version CI GitHub license Twitter Follow Discord

cigs are Ai typescript functions. They are composable intelligent generative snippets that offer new ways to build powerful applications leveraging the latest in Ai. Some call it the lodash for AI functions or GraphQL for code execution. cigs are powered by OpenAI structured outputs and function calling. In the future, we will support more LLMs and more structured output types but Structured outputs enables some powerful stuff.

cigs

Think of it like a combination of instructor, askmarvin, and fructose, but with a few main differences:

  • Uses OpenAI structured outputs: Structured outputs simplify a lot of the logic of these libraries!
  • Written in TypeScript: Lots of cool libraries for python, but TS is lacking :(
  • Chainable: Easily chain multiple cigs together to create complex workflows
  • Type Safe: Use Zod schemas to define the input and output of your cigs
  • Flexible: Call cigs with natural language or with structured inputs
  • Dynamic function response: You can define a typescript function with a specific input schema. You can then call that function with the input or natural language and specify the desired output schema at run time. We will use OpenAI structured outputs to map the function response to the desired output schema. So you can have one function be called from different places all with different type-safe outputs. Although not the same, I think of it like GrahpQL for code execution?

[!CAUTION] This library is still under development I will be erring on the side of speed, and possibly making drastic changes. Please join the Discord if you need help or something is broken Discord

What are cigs

  • Natural Language Execution: Run TypeScript functions using natural language inputs.
  • Composable Workflows: Chain multiple AI functions to create complex workflows.
  • Helper Functions: Simplify common tasks like classification, extraction, and generation.
  • Type Safety: Ensure structured outputs with Zod schemas.
  • Flexible Outputs: Call functions and get responses in specified formats.

Sounds weird, but with some examples it might make more sense

Installation

export OPENAI_API_KEY='...'    # currently required for core functionality

npm / node

npm install cigs
import cig, { z } from "cigs";

jsr

npx jsr add @cigs/cigs
import cig, { z } from "@cigs/cigs";

deno

deno add @cigs/cigs
import { cig, z } from "@cigs/cigs";

Current Supported Operations

cigs supports various operations that can be chained together:

  • schema: Transform the input to a specified output using a Zod schema
  • generate: Generate multiple outputs based on the schema
  • classify: Classify the input into predefined categories
  • handler: Apply a custom handler function
  • uses: Execute a series of tools (other cigs instances)
  • log: Add logging without modifying the data to intermediate steps
  • What else should we support?

cig supports the following configs

  • setModel: Set the OpenAI model to use
  • setLogLevel: Set the log level. 1 will show all the logs, 2 will show less etc
  • setDescription: Set the description of the cig. This will be passed to OpenAI
  • addInstruction: Add an instruction to the cig. This will be passed to OpenAI as the system prompt
  • addExample: Add an example to the cig. This will be passed to OpenAI to help tune the response
  • What else should we support?

Usage

Call a typescript function with natural language

[!TIP] Clone this repo and run this example with npm run example:handler

cigs wants to do a lot, but I think something cool about it is you can call a typescript function with natural language

Super simple example, but say you have this function:

function getUserCompliment(username: string) {
  const colorMap = {
    "Alice": "blue",
    "Bob": "green",
    "Charlie": "red",
  };
  return {
    color: colorMap[input.username as keyof typeof colorMap] || "unknown",
  };
}

You can call this function with natural language like this:

const userInfoSchema = z.object({
  username: z.string(),
});

// Define a cig to get a user's favorite color
const getFavoriteColor = cig("getFavoriteColor", userInfoSchema)
  .handler(async (input) => {
    // Simulated database lookup
    return getUserCompliment(input.username);
  });

// Usage example
(async () => {
  try {
    const result = await getFavoriteColor.run(
      "What is the favorite color of Alice",
    ); // { color: 'blue' }
    console.log(result);

    const result2 = await getFavoriteColor.run(
      "What is the favorite color of Susan",
    ); // { color: 'unknown' }
    console.log(result2);

    // You can also call that function with the specified input
    const result3 = await getFavoriteColor.run({ username: "Alice" }); // { color: 'blue' }
    console.log(result3);
    // Expected output: { username: 'alice', favoriteColor: 'blue', compliment: 'You have great taste!' }
  } catch (error) {
    console.error("Error:", error);
  }
})();

Initializing

There are a few ways to initialize a cigs instance

import cig, { z } from "@cigs/cigs";

const cig = cig("NAME", INPUT_ZOD_SCHEMA?, CONFIGURATOR?)

No configuration

// In the simplest case, you can just pass the name of the cig
const simplestCig = cig("my-cig")

// This won't do much of anything, but you can call it with natural language 
// and it will return essentially just the 
// raw output of OpenAI `openAIClient.chat.completions.create` call

const output = await simplestCig.run("Give me a random word");
// Serendipity

Just with a input schema. The input schema makes it so you can control the input of the cig. You are still able to call it with natural language and it will map it to the input schema, but you get typesafety for calling it with structured inputs. This is more useful when combined with handler functions, but can be used on its own

const simpleZodSchema = z.object({
  word: z.string(),
  command: z.string(),
});

const cigWithSchema = cig("my-cig", simpleZodSchema);

const result = await cigWithSchema.run({ word: "hello", command: "translate to french" });
// -> {"word":"hello","translation":"bonjour"}
// this output isn't super helpful. Its a string, so not a typed object
// It's just trying to match the input as best as possible. We will get better below

const result2 = await cigWithSchema.run("translate hello to french");
// -> "Hello" in French is "Bonjour."

Just with configuration. You can add instructions, examples, and more to help guide the cig. These can be applied when initializing the cig or when adding operations.

const cigWithConfig = cig("my-cig", (config) => {
  config.setModel("gpt-4o-2024-08-06");
  config.setLogLevel(1);
  config.setDescription("This is a test cig");
  config.addInstruction("Respond with the given phrase in french");
  config.addExample("I love you so much!", "Je t'aime");
});

const result = await cigWithConfig.run("wow this library is so cool");
// -> Wow, cette bibliothèque est tellement cool.

With everything

const simpleZodSchema = z.object({
  words: z.array(z.string()),
});

const cigWithConfig = cig("my-cig", simpleZodSchema, (config) => {
  config.setModel("gpt-4o-2024-08-06");
  config.setLogLevel(1);
  config.addInstruction("Given a list of words, return a sentence using all of them");
});

// Now run it:
const result = await cigWithConfig.run({ words: ["Dinosaur", "Typescript", "AI"] });
// -> Dinosaur enthusiasts have started using Typescript to create interactive AI exhibits in museums worldwide.

// And just like everything, you can also call it with natural language
const result = await cigWithConfig.run("please use the words Dinosaur, Typescript, and AI");
// It will be processed and mapped to the input schema
// {
//   context: 'Processed string input',
//   result: {
//     words: [
//       'Dinosaur',
//       'Typescript',
//       'AI'
//     ]
//   }
// }
// -> In an imaginative world, a dinosaur adeptly coded in TypeScript, creating an advanced AI to predict meteor showers.

So ya, it's pretty flexible and can handle a lot of different use cases. This doesn't show off the true power. It gets really fun when you start chaining cigs together and controlling the outputs.

Quick Start { simple }

[!TIP] Clone this repo and run this example with npm run example:simple

import cig, { z } from "@cigs/cigs";

const aiFunc = cig("ai-func", (config) => {
  config.setDescription(
    "You will a string of words respond with the most interesting word from them",
  );
  config.addExample("I love you so much!", "love");
  config.addExample("This food is delicious", "delicious");
  config.setModel("gpt-4o-2024-08-06");
  config.setLogLevel(1);
});

(async () => {
  try {
    const result = await a

Related Skills

View on GitHub
GitHub Stars64
CategoryProduct
Updated7mo ago
Forks4

Languages

TypeScript

Security Score

92/100

Audited on Aug 14, 2025

No findings