以编程方式使用文档

并非每个代理交互都是聊天。有时代理正在执行 多步骤计划,展示进度的最佳方式是 **待办事项列表** 它 实时更新。深度代理待办事项模式直接从 todos 数组 中读取,渲染每个项目及其当前状态 代理执行计划时。这是一个基于相同 useStream hook构建的进度仪表板。它表明代理状态可以为任何UI提供支持, 不仅仅是消息气泡。

工作原理

深度代理包含一个内置 **todos 状态** 来跟踪任务进度 代理执行计划时。当代理执行时,它会更新每个 待办事项的状态从 "pending" to "in_progress" to "completed"。该 useStream hook通过 stream.values.todos暴露此状态,您的UI 以响应式方式渲染它。

流程如下:

1. 用户提交请求 2. 代理创建计划并填充 todos 到其状态中 3. 代理开始执行每个待办事项,状态转换经过 pendingin_progresscompleted 4. stream.values.todos 随着代理进展实时更新 5. 您的UI会使用当前状态重新渲染待办事项列表

设置 useStream

无需特殊配置。指向useStream到您的代理并 读取 todosstream.values.

const AGENT_URL = "http://localhost:2024";

  const stream = useStream<typeof myAgent>({
    apiUrl: AGENT_URL,
    assistantId: "deep_agent_todo_list",
  });

  const todos = stream.values?.todos ?? [];

  return (


      {stream.messages.map((msg) => (

      ))}

  );
}
<script setup lang="ts">



const AGENT_URL = "http://localhost:2024";

const stream = useStream<typeof myAgent>({
  apiUrl: AGENT_URL,
  assistantId: "deep_agent_todo_list",
});

const todos = computed(() => stream.values.value?.todos ?? []);
</script>

<template>




</template>
<script lang="ts">


  const AGENT_URL = "http://localhost:2024";

  const stream = useStream<typeof myAgent>({
    apiUrl: AGENT_URL,
    assistantId: "deep_agent_todo_list",
  });

  const todos = $derived(stream.values?.todos ?? []);
</script>



  {#each stream.messages as msg (msg.id)}

  {/each}
const AGENT_URL = "http://localhost:2024";

@Component({
  selector: "app-todo-agent",
  template: `

      <app-todo-list [todos]="todos()" />
      @for (msg of stream.messages(); track msg.id) {
        <app-message [message]="msg" />
      }

  `,
})

  stream = injectStream<typeof myAgent>({
    apiUrl: AGENT_URL,
    assistantId: "deep_agent_todo_list",
  });

  todos = computed(() => this.stream.values()?.todos ?? []);
}

构建TodoList组件

待办事项列表使用状态图标、颜色编码和视觉效果渲染每个项目 来反映当前状态:

function TodoList({ todos }: { todos: Todo[] }) {
  const completed = todos.filter((t) => t.status === "completed").length;
  const percentage = todos.length
    ? Math.round((completed / todos.length) * 100)
    : 0;

  return (


        <h2 className="text-lg font-semibold">Agent Progress</h2>
        <span className="text-sm text-gray-500">
          {completed}/{todos.length} tasks
        </span>




      <ul className="mt-4 space-y-2">
        {todos.map((todo, i) => (

        ))}
      </ul>

  );
}

进度条

可视化进度条让用户一目了然地了解总体完成情况:

function ProgressBar({ percentage }: { percentage: number }) {
  return (


        <span>Progress</span>
        <span>{percentage}%</span>





  );
}

单个待办事项

每个项目都有状态图标、颜色编码的文本和 已完成任务的删除线样式:

function TodoItem({ todo }: { todo: Todo }) {
  const config = {
    pending: {
      icon: "○",
      textClass: "text-gray-600",
      bgClass: "bg-gray-50",
      iconClass: "text-gray-400",
    },
    in_progress: {
      icon: "◉",
      textClass: "text-amber-800",
      bgClass: "bg-amber-50 border-amber-200",
      iconClass: "text-amber-500 animate-pulse",
    },
    completed: {
      icon: "✓",
      textClass: "text-green-800 line-through",
      bgClass: "bg-green-50 border-green-200",
      iconClass: "text-green-500",
    },
  };

  const style = config[todo.status];

  return (
    <li
      className={`flex items-start gap-3 rounded-md border px-3 py-2 ${style.bgClass}`}
    >
      <span className={`mt-0.5 text-lg leading-none ${style.iconClass}`}>
        {style.icon}
      </span>
      <span className={`text-sm ${style.textClass}`}>{todo.content}</span>
    </li>
  );
}

in_progress 图标使用 animate-pulse 来突出显示当前 活动任务。

计算进度

直接从todos数组派生进度指标:

const todos = stream.values?.todos ?? [];

const completed = todos.filter((t) => t.status === "completed").length;
const inProgress = todos.filter((t) => t.status === "in_progress").length;
const pending = todos.filter((t) => t.status === "pending").length;
const percentage = todos.length
  ? Math.round((completed / todos.length) * 100)
  : 0;

当代理修改其状态时,这些值会响应式更新,保持 进度条和计数器的同步。

与聊天消息结合

待办事项列表可与常规聊天界面配合使用。一种实用的布局 将待办列表显示为持久化的侧边栏或标题栏面板,并与聊天消息一起展示 below:

function TodoAgentLayout() {
  const stream = useStream<typeof myAgent>({
    apiUrl: AGENT_URL,
    assistantId: "deep_agent_todo_list",
  });

  const todos = stream.values?.todos ?? [];

  return (

      {todos.length > 0 && (



      )}

      <main className="flex-1 overflow-y-auto p-6">

          {stream.messages.map((msg) => (

          ))}

      </main>


          stream.submit({ messages: [{ type: "human", content: text }] })
        }
        isLoading={stream.isLoading}
      />

  );
}

使用场景

待办列表模式适用于代理执行结构化操作的任何场景 plan:

- **项目规划**:代理将项目分解为任务并按顺序 依次完成 - **研究工作流程**:每个研究问题都会变成一个待办事项,由代理 调查并完成 - **数据处理**:如数据摄取、验证、转换等步骤

- **引导流程**:代理逐步完成设置流程,逐项勾选 同时配置服务 - **报告生成**:报告的各个部分变成待办事项:收集数据、 分析趋势、撰写摘要、格式化输出

处理空状态和加载状态

处理代理创建计划之前的初始状态:

function TodoList({ todos, isLoading }: { todos: Todo[]; isLoading: boolean }) {
  if (todos.length === 0 && !isLoading) {
    return null;
  }

  if (todos.length === 0 && isLoading) {
    return (


          <span className="animate-spin">⟳</span>
          Agent is creating a plan...


    );
  }

  return (



  );
}

最佳实践

- **突出显示待办列表**。它是基于计划的代理的主要进度指示器。 不要将其隐藏在折叠内容下方。 - **为状态转换添加动画效果**。平滑的过渡效果让代理感觉更 灵敏。使用 CSS 过渡处理背景色、文本装饰等属性, opacity. - **一次只高亮一个 in_progress 项目**。代理通常一次只处理一个任务。 如果有多个项目显示为 in_progress,界面会变得嘈杂。 考虑只让第一个项目闪烁。 - **折叠或淡化已完成的项目**。随着列表增长,已完成的项目 变得不那么重要。降低其视觉权重,让用户专注于正在进行的任务。 事项。 - **显示进度百分比**。像"67% 完成"这样的单一数字容易 理解,即使从房间另一侧也能看清。 - **保持待办列表同步**。由于 stream.values 更新是响应式的, 待办列表会自动保持最新状态。不要添加手动轮询或 刷新逻辑。