Skip to content

Latest commit

 

History

History
136 lines (109 loc) · 3.91 KB

README.md

File metadata and controls

136 lines (109 loc) · 3.91 KB

Human in the Loop with Cloudflare Agents

This example demonstrates how to implement human-in-the-loop functionality using Cloudflare Agents, allowing AI agents to request human approval before executing certain actions. This pattern is crucial for scenarios where human oversight and confirmation are required before taking important actions.

Overview

The implementation showcases:

  • AI agents that can request human approval for specific actions
  • Real-time communication between agents and humans using WebSocket connections
  • Persistent state management across agent lifecycles
  • Tool-based architecture for extensible agent capabilities

Key Components

  1. Agent Definition
export class HumanInTheLoop extends AIChatAgent<Env> {
  async onChatMessage(onFinish: StreamTextOnFinishCallback<any>) {
    return createDataStreamResponse({
      execute: async (dataStream) => {
        // Process messages and check for tool calls requiring confirmation
        const processedMessages = await processToolCalls({
          messages: this.messages,
          dataStream,
          tools: {
            getWeatherInformation: {
              requiresApproval: true,
              execute: async ({ city }) => {
                // Example tool implementation
                return `The weather in ${city} is sunny.`;
              },
            },
          },
        });

        // Stream response using the processed messages
        streamText({
          model: openai("gpt-4o"),
          messages: processedMessages,
          tools,
          onFinish,
        }).mergeIntoDataStream(dataStream);
      },
    });
  }
}
  1. React Client Integration
function Chat() {
  // Initialize agent and chat hooks
  const agent = useAgent({ agent: "human-in-the-loop" });
  const { messages, addToolResult } = useAgentChat({ agent });

  return (
    <div className="chat-container">
      {messages.map((message) => (
        <div key={message.id}>
          {/* Render normal messages */}
          {message.type === "text" && (
            <div className="message">{message.content}</div>
          )}

          {/* Render tool approval requests */}
          {message.type === "tool-invocation" && (
            <div className="tool-approval">
              <p>
                Approve {message.tool} for {message.args.city}?
              </p>
              <button onClick={() => addToolResult(message.id, "approve")}>
                Yes
              </button>
              <button onClick={() => addToolResult(message.id, "reject")}>
                No
              </button>
            </div>
          )}
        </div>
      ))}
    </div>
  );
}

Features

  • Persistent State: Agent state persists across sessions using Cloudflare's durable storage
  • Real-time Updates: WebSocket connections ensure immediate updates for approval requests
  • Tool Registry: Flexible tool system with configurable approval requirements
  • Type Safety: Full TypeScript support for tool definitions and parameters

Getting Started

  1. Install dependencies:
npm install
  1. Configure your wrangler.toml:
[[durable_objects.bindings]]
binding = "HumanInTheLoop"
class_name = "HumanInTheLoop"

[[migrations]]
tag = "v1"
new_sqlite_classes = ["HumanInTheLoop"]
  1. Deploy your agent:
wrangler deploy
  1. Connect from your frontend using the React hooks provided by agents/react

Best Practices

  • Define clear approval workflows for sensitive operations
  • Implement timeouts for approval requests
  • Provide detailed context in approval requests
  • Handle connection drops and reconnections gracefully
  • Log all approval decisions for audit trails
  • Ensure proper error handling and fallbacks

Learn More