Skip to Content
Quickstart

Quickstart

In this quickstart, you’ll learn how to get up and running with GenSX. GenSX is a simple typescript framework for building complex LLM applications using JSX. If you haven’t already, check out the basic concepts to learn more about how GenSX works.

Prerequisites

Before getting started, make sure you have the following:

Install the gensx CLI

You can install the gensx CLI using your package manager of choice:

# For a global installation npm i -g gensx # or prefix every command with npx npx gensx

Login to GenSX Cloud (optional)

If you want to be able to visualize your workflows and view traces, you’ll need to login to GenSX Cloud:

blog writing trace

Run the following command to log into GenSX Cloud:

# If you installed the CLI globally gensx login # Using npx npx gensx login

Now traces will automatically be saved to the cloud so you can visualize and debug workflow executions, but this step is optional and you can skip it for now if you prefer.

gensx login

Hit enter and your browser will open the login page.

console login

Once you’ve logged in, you’ll see the following success message:

login success

Now you’re ready to create a new workflow! Return to your terminal for the next steps.

Create a new workflow

To get started, run the following command with your package manager of choice in an empty directory. This will create a new GenSX workflow to get you started.

# If you installed the CLI globally gensx new . # Using npx npx gensx new .

This will create a new started project, ready for you to run your first workflow:

create project

In index.tsx, you’ll find a simple OpenAI chat completion component:

import * as gensx from "@gensx/core"; import { OpenAIProvider, ChatCompletion } from "@gensx/openai"; interface RespondProps { userInput: string; } type RespondOutput = string; const Respond = gensx.Component<RespondProps, RespondOutput>( "Respond", async ({ userInput }) => { return ( <ChatCompletion model="gpt-4o-mini" messages={[ { role: "system", content: "You are a helpful assistant. Respond to the user's input.", }, { role: "user", content: userInput }, ]} /> ); }, ); const WorkflowComponent = gensx.Component<{ userInput: string }, string>( "Workflow", ({ userInput }) => ( <OpenAIProvider apiKey={process.env.OPENAI_API_KEY}> <Respond userInput={userInput} /> </OpenAIProvider> ), ); const workflow = gensx.Workflow("MyGSXWorkflow", WorkflowComponent); const result = await workflow.run({ userInput: "Hi there! Say 'Hello, World!' and nothing else.", }); console.log(result);

The component is executed through gensx.Workflow.run(), which processes the JSX tree from top to bottom. In this example:

  1. First, the OpenAIProvider component is initialized with your API key
  2. Then, the Respond component receives the userInput prop
  3. Inside Respond, a ChatCompletion component is created with the specified model and messages
  4. The result flows back up through the tree, ultimately returning the response from gpt-4o-mini.

Components in GenSX are pure functions that take props and return outputs, making them easy to test and compose. The JSX structure makes the data flow clear and explicit - each component’s output can be used by its children through standard TypeScript/JavaScript.

Running the workflow

To run the workflow, you’ll need to set the OPENAI_API_KEY environment variable.

# Set the environment variable export OPENAI_API_KEY=<your-api-key> # Run the project pnpm dev

run project

If you chose to log in, you can now view the trace for this run in GenSX Cloud by clicking the link:

trace

The trace shows a flame graph of your workflow, including every component that executed with inputs and outputs.

Some components will be hidden by default, but you can click the carat to expand them. Clicking on a component will show you details about it’s input props and outputs.

For longer running workflows, this view will update in real time as the workflow executes.

Combining components

The example above is a simple workflow with a single component. In practice, you’ll often want to combine multiple components to create more complex workflows.

Components can be nested to create multi-step workflows with each component’s output being passed through a child function. For example, let’s define two components: a Research component that gathers information about a topic, and a Writer component that uses that information to write a blog post.

// Research component that gathers information const Research = gensx.Component<{ topic: string }, string>( "Research", async ({ topic }) => { return ( <ChatCompletion model="gpt-4o-mini" messages={[ { role: "system", content: "You are a research assistant. Provide key facts about the topic.", }, { role: "user", content: topic }, ]} /> ); }, ); // Writer component that uses research to write content const WriteArticle = gensx.Component< { topic: string; research: string }, string >("WriteArticle", async ({ topic, research }) => { return ( <ChatCompletion model="gpt-4o-mini" messages={[ { role: "system", content: "You are a content writer. Use the research provided to write a blog post about the topic.", }, { role: "user", content: `Topic: ${topic}\nResearch: ${research}` }, ]} /> ); });

Now you can combine these components using a child function:

// Combine components using child functions const ResearchAndWrite = gensx.Component<{ topic: string }, string>( "ResearchAndWrite", ({ topic }) => ( <OpenAIProvider apiKey={process.env.OPENAI_API_KEY}> <Research topic={topic}> {(research) => <WriteArticle topic={topic} research={research} />} </Research> </OpenAIProvider> ), ); const workflow = gensx.Workflow("ResearchAndWriteWorkflow", ResearchAndWrite, { printUrl: true, });

In this example, the Research component gathers information about the topic which then passes the information to the WriteArticle component. The WriteArticle component uses that information to write an article about the topic which is then returned as the result.

Streaming

One common challenge with LLM workflows is handling streaming responses. Any given LLM call can return a response as a string or as a stream of tokens. Typically you’ll want the last component of your workflow to stream the response.

To take advantage of streaming, all you need to do is update the WriteArticle component to use StreamComponent and set the stream prop to true in the ChatCompletion component.

interface WriterProps { topic: string; research: string; stream?: boolean; } const Writer = gensx.StreamComponent<WriterProps>( "Writer", async ({ topic, research, stream }) => { return ( <ChatCompletion stream={stream ?? false} model="gpt-4o-mini" messages={[ { role: "system", content: "You are a content writer. Use the research provided to write a blog post about the topic.", }, { role: "user", content: `Topic: ${topic}\nResearch: ${research}` }, ]} /> ); }, ); const ResearchAndWrite = gensx.Component<{ topic: string }, string>( "ResearchAndWrite", ({ topic }) => ( <OpenAIProvider apiKey={process.env.OPENAI_API_KEY}> <Research topic={topic}> {(research) => ( <Writer topic="latest quantum computing chips" research={research} stream={true} /> )} </Research> </OpenAIProvider> ), ); const workflow = gensx.Workflow("ResearchAndWriteWorkflow", ResearchAndWrite); const stream = await workflow.run( { topic: "latest quantum computing chips" }, { printUrl: true }, ); // Print the streaming response for await (const chunk of stream) { process.stdout.write(chunk); }

Now we can see our research step running before the write step:

streaming

While this is nice, the real power of streaming components comes when you expand or refactor your workflow. Now you could easily add an <EditArticle> component to the workflow that streams the response to the user with minimal changes. There’s no extra plumbing needed besides removing the stream={true} prop on the WriteArticle component.

const ResearchAndWrite = gensx.Component<{ topic: string }, string>( "ResearchAndWrite", ({ topic }) => ( <OpenAIProvider apiKey={process.env.OPENAI_API_KEY}> <Research topic={topic}> {(research) => ( <WriteArticle topic={topic} research={research}> {(content) => <EditArticle content={content} stream={true}/>} </WriteArticle> )} </Research> </OpenAIProvider>, ); const workflow = gensx.Workflow("ResearchAndWriteWorkflow", ResearchAndWrite, { printUrl: true }); const stream = await workflow.run({ topic: "latest quantum computing chips" });

blog writing trace

Next steps

Now that you’ve gone through the quickstart, you should be able to start building with GenSX. Take a look at the following examples to see how you can build more complex workflows.

Last updated on