From 56d111c53c84c878fcaddfe12f94ce3d6ebe3b40 Mon Sep 17 00:00:00 2001 From: akhisud3195 Date: Sun, 13 Jul 2025 11:51:27 +0530 Subject: [PATCH] Add JSON mode and wrap for internal agents and tool calls --- apps/rowboat/app/lib/agent_instructions.ts | 20 +++ apps/rowboat/app/lib/agents.ts | 7 +- .../projects/[projectId]/playground/app.tsx | 2 +- .../playground/components/chat.tsx | 3 + .../playground/components/messages.tsx | 127 ++++++++++++++++-- 5 files changed, 144 insertions(+), 15 deletions(-) diff --git a/apps/rowboat/app/lib/agent_instructions.ts b/apps/rowboat/app/lib/agent_instructions.ts index 76ed7bc3..593d4e70 100644 --- a/apps/rowboat/app/lib/agent_instructions.ts +++ b/apps/rowboat/app/lib/agent_instructions.ts @@ -106,4 +106,24 @@ export const CHILD_TRANSFER_RELATED_INSTRUCTIONS = ` 3. Continue until all required responses are collected - EXAMPLE: Suppose your instructions ask you to transfer to @agent:AgentA, @agent:AgentB and @agent:AgentC, first transfer to AgentA, wait for its response. Then transfer to AgentB, wait for its response. Then transfer to AgentC, wait for its response. Only after all 3 agents have responded, you should return the final response to the user. +`; + +export const CONVERSATION_TYPE_INSTRUCTIONS = (): string => ` +- You are an agent that is part of a workflow of (one or more) interconnected agents that work together to be an assistant. +- You will be directly interacting with the user. +- It is possible that some other agent might have invoked you to talk to the user. +- Reading the messages in the chat history will give you context about the conversation. But importantly, your response should simply be the direct text to the user. Do not put out a JSON with any internal information - other agents might do so but that is because they are internal agents. +- Seeing the tool calls that transfer / handoff control will help you understand the flow of the conversation and which agent produced each message. +- When using internal messages that other agents have put out, make sure to write it in a way that is suitable to be shown to the user and in accordance with further instructions below. +- These are high level instructions only. The user will provide more specific instructions which will be below. +`; + +export const TASK_TYPE_INSTRUCTIONS = (): string => ` +- You are an agent that is part of a workflow of (one or more) interconnected agents that work together to be an assistant. +- While you will put out a message, your response will not be shown directly to the user. Instead, your response will be used by the agent that might have invoked you and (possibly) other agents in the workflow. Therefore, your responses must be put out in such a way that it is useful for other agents and not addressed to the user. +- Use the JSON format to convey your responses. +- The first key in the JSON response should be your "thought" - analysizing what has happened till now and what you need to do in this turn.The last key in the JSON response should be 'notes_to_self' which you will use to track what you have finished and what's left to do if any. +- Reading the messages in the chat history will give you context about the conversation. +- Seeing the tool calls that transfer / handoff control will help you understand the flow of the conversation and which agent produced each message. +- These are high level instructions only. The user will provide more specific instructions which will be below. `; \ No newline at end of file diff --git a/apps/rowboat/app/lib/agents.ts b/apps/rowboat/app/lib/agents.ts index f5e300db..c46424d9 100644 --- a/apps/rowboat/app/lib/agents.ts +++ b/apps/rowboat/app/lib/agents.ts @@ -17,7 +17,7 @@ import { dataSourceDocsCollection, dataSourcesCollection, projectsCollection } f import { qdrantClient } from '../lib/qdrant'; import { EmbeddingRecord } from "./types/datasource_types"; import { ConnectedEntity, sanitizeTextWithMentions, Workflow, WorkflowAgent, WorkflowPrompt, WorkflowTool } from "./types/workflow_types"; -import { CHILD_TRANSFER_RELATED_INSTRUCTIONS, RAG_INSTRUCTIONS } from "./agent_instructions"; +import { CHILD_TRANSFER_RELATED_INSTRUCTIONS, CONVERSATION_TYPE_INSTRUCTIONS, RAG_INSTRUCTIONS, TASK_TYPE_INSTRUCTIONS } from "./agent_instructions"; import { PrefixLogger } from "./utils"; import { Message, AssistantMessage, AssistantMessageWithToolCalls, ToolMessage } from "./types/types"; @@ -502,7 +502,12 @@ ${config.name} ## Description ${config.description} +## About You + +${config.outputVisibility === 'user_facing' ? CONVERSATION_TYPE_INSTRUCTIONS() : TASK_TYPE_INSTRUCTIONS()} + ## Instructions + ${config.instructions} ${config.examples ? ('# Examples\n' + config.examples) : ''} diff --git a/apps/rowboat/app/projects/[projectId]/playground/app.tsx b/apps/rowboat/app/projects/[projectId]/playground/app.tsx index 78e8791a..07082a16 100644 --- a/apps/rowboat/app/projects/[projectId]/playground/app.tsx +++ b/apps/rowboat/app/projects/[projectId]/playground/app.tsx @@ -10,7 +10,7 @@ import { Tooltip } from "@heroui/react"; import { TestProfile } from "@/app/lib/types/testing_types"; import { WithStringId } from "@/app/lib/types/types"; import { ProfileSelector } from "@/app/projects/[projectId]/test/[[...slug]]/components/selectors/profile-selector"; -import { CheckIcon, CopyIcon, PlusIcon, UserIcon, InfoIcon, BugIcon, BugOffIcon } from "lucide-react"; +import { CheckIcon, CopyIcon, PlusIcon, UserIcon, InfoIcon, BugIcon, BugOffIcon, CodeIcon } from "lucide-react"; import { USE_TESTING_FEATURE } from "@/app/lib/feature_flags"; import { clsx } from "clsx"; diff --git a/apps/rowboat/app/projects/[projectId]/playground/components/chat.tsx b/apps/rowboat/app/projects/[projectId]/playground/components/chat.tsx index 032fffce..a69e730f 100644 --- a/apps/rowboat/app/projects/[projectId]/playground/components/chat.tsx +++ b/apps/rowboat/app/projects/[projectId]/playground/components/chat.tsx @@ -27,6 +27,7 @@ export function Chat({ toolWebhookUrl, onCopyClick, showDebugMessages = true, + showJsonMode = false, projectTools, }: { chat: z.infer; @@ -41,6 +42,7 @@ export function Chat({ toolWebhookUrl: string; onCopyClick: (fn: () => string) => void; showDebugMessages?: boolean; + showJsonMode?: boolean; projectTools: z.infer[]; }) { const [messages, setMessages] = useState[]>(chat.messages); @@ -299,6 +301,7 @@ export function Chat({ onSystemMessageChange={onSystemMessageChange} showSystemMessage={false} showDebugMessages={showDebugMessages} + showJsonMode={showJsonMode} /> {showUnreadBubble && ( + {jsonMode && ( + + )} + + )} + {isJsonContent && jsonMode ? ( +
+                                        {formattedJson}
+                                    
+ ) : ( + + )}
+ ) : undefined} + /> +
+ )} @@ -282,12 +369,18 @@ function ExpandableContent({ label, content, expanded = false, - icon + icon, + wrapText = false, + onExpandedChange, + rightButton }: { label: string, content: string | object | undefined, expanded?: boolean, - icon?: React.ReactNode + icon?: React.ReactNode, + wrapText?: boolean, + onExpandedChange?: (expanded: boolean) => void, + rightButton?: React.ReactNode }) { const [isExpanded, setIsExpanded] = useState(expanded); @@ -308,7 +401,9 @@ function ExpandableContent({ }, [content]); function toggleExpanded() { - setIsExpanded(!isExpanded); + const newExpanded = !isExpanded; + setIsExpanded(newExpanded); + onExpandedChange?.(newExpanded); } const isMarkdown = label === 'Result' && typeof content === 'string' && !content.startsWith('{'); @@ -319,6 +414,7 @@ function ExpandableContent({ {isExpanded && } {icon && {icon}}
{label}
+ {rightButton && {rightButton}} {isExpanded && ( isMarkdown ? ( @@ -327,7 +423,9 @@ function ExpandableContent({ ) : (
                     {formattedContent}
@@ -348,6 +446,7 @@ export function Messages({
     onSystemMessageChange,
     showSystemMessage,
     showDebugMessages = true,
+    showJsonMode = false,
 }: {
     projectId: string;
     messages: z.infer[];
@@ -359,6 +458,7 @@ export function Messages({
     onSystemMessageChange: (message: string) => void;
     showSystemMessage: boolean;
     showDebugMessages?: boolean;
+    showJsonMode?: boolean;
 }) {
     // Remove scroll/auto-scroll state and logic
     // const scrollContainerRef = useRef(null);
@@ -408,6 +508,7 @@ export function Messages({
                         sender={message.agentName ?? ''}
                         latency={latency}
                         delta={latency}
+                        showJsonMode={showJsonMode}
                     />
                 );
             }