Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,11 @@ The allowed actions are:
- `Respond` - If you send a text response back, it will be used to rewrite the email in some way, then interrupt again and wait for you to take an action.
- `Ignore` - This will send back an `ignore` response, and the graph will end without taking any actions.
- `Mark as resolved` - If you select this, it will resume the graph, but starting at the `__end__` node, causing the graph to end without taking any actions.

## Writer Agent

This is a dummy agent used to demonstrate how you can stream generative UI components as an artifact. It should be accessed via the `writer` graph ID. It should be accessed via the `agent` graph ID, which means you'll need to go through the Supervisor agent to access it. The following prompts will trigger the writer agent:

- `Write me a short story about a <insert topic here>`

This will render a generative UI component that contains the title and content of your short story. The generative UI component will be rendered in a side panel to the right of the chat and the contents of the story will be streamed to the UI as it is generated.
57 changes: 32 additions & 25 deletions src/agent-uis/utils/use-artifact.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { Message } from "@langchain/langgraph-sdk";
import { useStreamContext, UIMessage } from "@langchain/langgraph-sdk/react-ui";

// eslint-disable-next-line react-refresh/only-export-components
const NoopPreview = () => null;

// eslint-disable-next-line react-refresh/only-export-components
const NoopSetOpen = () => void 0;

// eslint-disable-next-line react-refresh/only-export-components
const NoopSetContext = () => void 0;

const NoopContext = {};

import { useMemo } from "react";
import type { Message } from "@langchain/langgraph-sdk";
import {
useStreamContext,
type UIMessage,
} from "@langchain/langgraph-sdk/react-ui";

/**
* Hook that obtains the artifact context provided by the `LoadExternalComponent`
* found in the `meta.artifact` field.
*
* @see https://github.com/langchain-ai/agent-chat-ui/blob/main/src/components/thread/messages/ai.tsx
*/
export function useArtifact<TContext = Record<string, unknown>>() {
type Component = (props: {
children: React.ReactNode;
title?: React.ReactNode;
}) => React.ReactNode;

type Context = TContext | undefined;

type Bag = {
open: boolean;
setOpen: (value: boolean | ((prev: boolean) => boolean)) => void;
Expand All @@ -28,17 +29,23 @@ export function useArtifact<TContext = Record<string, unknown>>() {

const thread = useStreamContext<
{ messages: Message[]; ui: UIMessage[] },
{ MetaType: { artifact: { content: Component } & Bag } }
{ MetaType: { artifact: [Component, Bag] } }
>();

return [
thread.meta?.artifact?.content ?? NoopPreview,
{
open: thread.meta?.artifact?.open ?? false,
setOpen: thread.meta?.artifact?.setOpen ?? NoopSetOpen,

context: thread.meta?.artifact?.context ?? NoopContext,
setContext: thread.meta?.artifact?.setContext ?? NoopSetContext,
},
] as [Component, Bag];
const noop = useMemo(
() =>
[
() => null,
{
open: false,
setOpen: () => void 0,

context: {} as TContext,
setContext: () => void 0,
},
] as [Component, Bag],
[],
);

return thread.meta?.artifact ?? noop;
}
Loading