Skip to content

Conversation

Copy link

Copilot AI commented Dec 6, 2025

Implements a hybrid architecture where BotSharp handles authentication, routing, and control while delegating complex content generation to Dify workflows via REST API integration.

Implementation

Plugin Core

  • DifyPlugin - IBotSharpPlugin implementation with DI registration
  • CallDifyWorkflowFn - IFunctionCallback for sync/async workflow execution
  • DifyWorkflowService - HTTP client for Dify API (POST /v1/workflows/{id}/run)

Async Task Management

  • DifyTaskPollingService - BackgroundService that polls workflow status at configurable intervals
  • DifyTaskStorageService - Thread-safe in-memory task tracking (replaceable with persistent storage)
  • Handles task lifecycle: Running → Succeeded/Failed with timeout support

Models

  • DifyWorkflowRequest/Response - API DTOs matching Dify's schema
  • DifyWorkflowTask - Internal task state with polling attempt tracking
  • DifyWorkflowArgs - Function arguments from LLM calls

Usage

{
  "function": "dify-workflow-execute",
  "arguments": {
    "workflow_id": "data-analyzer",
    "inputs": "{\"sales_data\": {...}, \"format\": \"summary\"}",
    "async": true,
    "conversation_id": "conv-123"
  }
}

Sync mode: Blocks until completion, suitable for <30s tasks
Async mode: Returns task_id immediately, polls in background, supports session resumption

Configuration

{
  "Dify": {
    "BaseUrl": "https://api.dify.ai",
    "ApiKey": "your-key",
    "PollingIntervalSeconds": 10,
    "MaxPollingAttempts": 180,
    "TimeoutSeconds": 300
  }
}

Testing

10 unit tests covering task storage, model initialization, and state transitions. In-memory storage is production-ready pattern for replacement with Redis/SQL.

Architecture Decision

Polling-based status checking chosen due to Dify's lack of webhook support. Designed for webhook replacement when available. Background service prevents thread blocking during long-running workflows (minutes to hours).

Original prompt

鉴于BotSharp在管控上的优势和Dify在生成与编排上的灵活性,构建一个 BotSharp Router + Dify Workflow 的混合架构不仅可行,而且是企业级AI的最佳实践。
6.1 架构蓝图:Router 作为上层调度器
在这个设想的架构中,BotSharp扮演“大脑”和“守门员”的角色,而Dify则作为“手脚”和“创意引擎”。
场景: 用户请求“分析附件中的销售报表,并给CEO写一封总结邮件”。
分层调度逻辑:
BotSharp层(接入与鉴权): BotSharp接收请求,通过中间件验证用户是否有权访问CEO邮箱和销售数据。
BotSharp Router(宏观路由): 识别出任务包含“数据分析”和“邮件撰写”两个步骤。
BotSharp Planner(任务分解):
子任务A(数据提取):调用本地C#服务 SalesDataService.GetLastQuarterData(),这是刚性操作,必须准确。
子任务B(内容生成):将子任务A获取的Raw Data作为参数,调用 Dify 的 Workflow API。
Dify层(微观执行): Dify 接收到JSON数据,运行一个包含“数据清洗 -> 洞察提取 -> 邮件润色”的复杂工作流。这一步利用Dify在Prompt编排上的优势,生成高质量文本。
BotSharp层(结果投递): Dify返回生成的邮件草稿。BotSharp调用Exchange API发送邮件,并记录审计日志。
6.2 技术实现关键点
6.2.1 接口对接与协议映射
BotSharp需要开发一个通用的 DifyPlugin,实现 IFunctionExecutor 接口。
调用方式: 使用 Dify 的 REST API (POST /v1/workflows/run) 26。
数据契约: BotSharp需将C#对象序列化为Dify所需的 inputs JSON格式。例如,C#中的 List 需要转换为Dify Workflow 定义的 string 或 json 类型输入变量 27。
6.2.2 异步任务与回调机制(Async & Webhook)
这是集成中最大的技术挑战。Dify的工作流(特别是包含Agent Node的)可能运行数分钟。BotSharp不能一直阻塞线程等待HTTP响应。
问题: Dify 原生API 主要支持 blocking(阻塞)和 streaming(流式)。对于后台任务,虽然可以异步执行,但Dify目前缺乏完善的、主动推送任务完成状态的Webhook机制 29。
解决方案: 必须在BotSharp侧实现一个 轮询(Polling)机制。
BotSharp发起请求,Dify返回 task_id。
BotSharp将该任务挂起(Suspend),并将 task_id 存入状态库。
一个后台的C# HostedService 定时轮询 Dify 的 /v1/workflows/run/{task_id} 接口检查状态 28。
任务完成后,HostedService 唤醒挂起的BotSharp会话,继续后续流程。


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 4 commits December 6, 2025 10:50
Co-authored-by: geffzhang <439390+geffzhang@users.noreply.github.com>
Co-authored-by: geffzhang <439390+geffzhang@users.noreply.github.com>
…tation

Co-authored-by: geffzhang <439390+geffzhang@users.noreply.github.com>
Co-authored-by: geffzhang <439390+geffzhang@users.noreply.github.com>
Copilot AI changed the title [WIP] Construct BotSharp Router and Dify Workflow architecture Add BotSharp.Plugin.Dify for hybrid workflow orchestration Dec 6, 2025
Copilot AI requested a review from geffzhang December 6, 2025 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants