diff --git a/internal/ai/application/runtime/service.go b/internal/ai/application/runtime/service.go
index 343a9fa..6e3f3e7 100644
--- a/internal/ai/application/runtime/service.go
+++ b/internal/ai/application/runtime/service.go
@@ -24,7 +24,11 @@ func NewService() *Service {
func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) {
req.UserMessage.Content = utils.BuildRuntimeMessageText(req.UserMessage.MessageType, req.UserMessage.Content)
- req.AIAgent = applyWorkflowInstruction(req.AIAgent)
+ aiAgent, err := prepareWorkflowAgent(req.AIAgent)
+ if err != nil {
+ return nil, err
+ }
+ req.AIAgent = aiAgent
toolSet, err := s.prepare.prepareToolsForRun(req)
if err != nil {
return nil, err
@@ -45,7 +49,11 @@ func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) {
}
func (s *Service) Resume(ctx context.Context, req ResumeRequest) (*Summary, error) {
- req.AIAgent = applyWorkflowInstruction(req.AIAgent)
+ aiAgent, err := prepareWorkflowAgent(req.AIAgent)
+ if err != nil {
+ return nil, err
+ }
+ req.AIAgent = aiAgent
toolSet, err := s.prepare.prepareToolsForResume(req)
if err != nil {
return nil, err
diff --git a/internal/ai/application/runtime/tool_catalog.go b/internal/ai/application/runtime/tool_catalog.go
index ac31a81..1f27d95 100644
--- a/internal/ai/application/runtime/tool_catalog.go
+++ b/internal/ai/application/runtime/tool_catalog.go
@@ -82,7 +82,7 @@ func (c *toolCatalog) parseAgentAllowedToolCodes(aiAgent models.AIAgent) []strin
ret = append(ret, graphTools...)
}
}
- if result, ok := resolveAgentWorkflow(aiAgent); ok {
+ if result, err := resolveAgentWorkflow(aiAgent); err == nil {
ret = append(ret, result.ToolCodes...)
}
return toolx.NormalizeToolCodes(ret)
diff --git a/internal/ai/application/runtime/tool_catalog_test.go b/internal/ai/application/runtime/tool_catalog_test.go
index 8b0c29e..94717fe 100644
--- a/internal/ai/application/runtime/tool_catalog_test.go
+++ b/internal/ai/application/runtime/tool_catalog_test.go
@@ -85,7 +85,6 @@ func TestToolCatalogIncludesPublishedWorkflowGraphTools(t *testing.T) {
catalog := newToolCatalog()
ret := catalog.parseAgentAllowedToolCodes(models.AIAgent{
- RuntimeMode: enums.AIAgentRuntimeModeWorkflow,
WorkflowVersionID: version.ID,
})
@@ -94,7 +93,7 @@ func TestToolCatalogIncludesPublishedWorkflowGraphTools(t *testing.T) {
assertContainsToolCode(t, ret, toolx.GraphHandoffConversation.Code)
}
-func TestApplyWorkflowInstructionAppendsPublishedWorkflow(t *testing.T) {
+func TestPrepareWorkflowAgentAppendsPublishedWorkflow(t *testing.T) {
setupWorkflowRuntimeTestDB(t)
version := createWorkflowRuntimeTestVersion(t, dsl.Definition{
SchemaVersion: 1,
@@ -105,11 +104,13 @@ func TestApplyWorkflowInstructionAppendsPublishedWorkflow(t *testing.T) {
},
})
- agent := applyWorkflowInstruction(models.AIAgent{
+ agent, err := prepareWorkflowAgent(models.AIAgent{
SystemPrompt: "Base prompt.",
- RuntimeMode: enums.AIAgentRuntimeModeWorkflow,
WorkflowVersionID: version.ID,
})
+ if err != nil {
+ t.Fatalf("prepare workflow agent: %v", err)
+ }
if agent.SystemPrompt == "Base prompt." {
t.Fatalf("expected workflow appendix to be appended")
}
@@ -118,6 +119,39 @@ func TestApplyWorkflowInstructionAppendsPublishedWorkflow(t *testing.T) {
}
}
+func TestPrepareWorkflowAgentRejectsMissingPublishedWorkflow(t *testing.T) {
+ _, err := prepareWorkflowAgent(models.AIAgent{})
+ if err == nil {
+ t.Fatalf("expected missing workflow version error")
+ }
+ if !strings.Contains(err.Error(), "workflow version is required") {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestPrepareWorkflowAgentRejectsDeletedPublishedWorkflow(t *testing.T) {
+ setupWorkflowRuntimeTestDB(t)
+ version := createWorkflowRuntimeTestVersion(t, dsl.Definition{
+ SchemaVersion: 1,
+ EntryNodeID: "start",
+ Nodes: []dsl.Node{
+ {ID: "start", Type: workflowregistry.NodeTypeStart, Name: "Start"},
+ {ID: "end", Type: workflowregistry.NodeTypeEnd, Name: "End"},
+ },
+ })
+ if err := sqls.DB().Model(&models.AIWorkflowVersion{}).Where("id = ?", version.ID).Update("status", enums.StatusDeleted).Error; err != nil {
+ t.Fatalf("delete workflow version: %v", err)
+ }
+
+ _, err := prepareWorkflowAgent(models.AIAgent{WorkflowVersionID: version.ID})
+ if err == nil {
+ t.Fatalf("expected invalid workflow version error")
+ }
+ if !strings.Contains(err.Error(), "workflow version does not exist") {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
func setupWorkflowRuntimeTestDB(t *testing.T) {
t.Helper()
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=shared"), &gorm.Config{})
diff --git a/internal/ai/application/runtime/workflow_runtime.go b/internal/ai/application/runtime/workflow_runtime.go
index 2042972..3b702ee 100644
--- a/internal/ai/application/runtime/workflow_runtime.go
+++ b/internal/ai/application/runtime/workflow_runtime.go
@@ -8,37 +8,41 @@ import (
"agent-desk/internal/ai/workflow/dsl"
"agent-desk/internal/models"
"agent-desk/internal/pkg/enums"
+ "agent-desk/internal/pkg/errorsx"
"agent-desk/internal/repositories"
"github.com/mlogclub/simple/sqls"
)
-func resolveAgentWorkflow(aiAgent models.AIAgent) (compiler.Result, bool) {
- if aiAgent.RuntimeMode != enums.AIAgentRuntimeModeWorkflow || aiAgent.WorkflowVersionID <= 0 {
- return compiler.Result{}, false
+func resolveAgentWorkflow(aiAgent models.AIAgent) (compiler.Result, error) {
+ if aiAgent.WorkflowVersionID <= 0 {
+ return compiler.Result{}, errorsx.InvalidParam("workflow version is required")
}
version := repositories.AIWorkflowVersionRepository.Get(sqls.DB(), aiAgent.WorkflowVersionID)
if version == nil || version.Status != enums.StatusOk {
- return compiler.Result{}, false
+ return compiler.Result{}, errorsx.InvalidParam("workflow version does not exist")
}
var def dsl.Definition
if err := json.Unmarshal([]byte(version.Definition), &def); err != nil {
- return compiler.Result{}, false
+ return compiler.Result{}, errorsx.InvalidParam("workflow definition is invalid")
}
- return compiler.Compile(def), true
+ return compiler.Compile(def), nil
}
-func applyWorkflowInstruction(aiAgent models.AIAgent) models.AIAgent {
- result, ok := resolveAgentWorkflow(aiAgent)
- if !ok || strings.TrimSpace(result.Appendix) == "" {
- return aiAgent
+func prepareWorkflowAgent(aiAgent models.AIAgent) (models.AIAgent, error) {
+ result, err := resolveAgentWorkflow(aiAgent)
+ if err != nil {
+ return aiAgent, err
+ }
+ if strings.TrimSpace(result.Appendix) == "" {
+ return aiAgent, nil
}
prompt := strings.TrimSpace(aiAgent.SystemPrompt)
appendix := strings.TrimSpace(result.Appendix)
if prompt == "" {
aiAgent.SystemPrompt = appendix
- return aiAgent
+ return aiAgent, nil
}
aiAgent.SystemPrompt = prompt + "\n\n" + appendix
- return aiAgent
+ return aiAgent, nil
}
diff --git a/internal/handlers/dashboard/ai_agent_handler.go b/internal/handlers/dashboard/ai_agent_handler.go
index cb39e1f..768cd93 100644
--- a/internal/handlers/dashboard/ai_agent_handler.go
+++ b/internal/handlers/dashboard/ai_agent_handler.go
@@ -189,8 +189,6 @@ func buildAIAgentResponseWithLocale(item *models.AIAgent, locale string) respons
Teams: make([]response.AIAgentTeamResponse, 0),
DirectTools: make([]response.AIAgentMCPToolResponse, 0),
GraphTools: make([]string, 0),
- RuntimeMode: item.RuntimeMode,
- RuntimeModeName: enums.GetAIAgentRuntimeModeLabel(item.RuntimeMode),
WorkflowVersionID: item.WorkflowVersionID,
SortNo: item.SortNo,
CreatedAt: item.CreatedAt.Format("2006-01-02 15:04:05"),
diff --git a/internal/models/models.go b/internal/models/models.go
index c467d64..d19d326 100644
--- a/internal/models/models.go
+++ b/internal/models/models.go
@@ -527,7 +527,6 @@ type AIAgent struct {
SkillIDs string `gorm:"type:varchar(500);not null;default:''"` // SkillIDs 为绑定的技能ID列表,按顺序表示允许路由的范围。
AllowedMCPTools string `gorm:"type:text"` // AllowedMCPTools 为允许 direct tool 路由的 MCP 工具白名单配置JSON。
AllowedGraphTools string `gorm:"type:text"` // AllowedGraphTools 为允许 Graph Tool 的白名单配置JSON。
- RuntimeMode enums.AIAgentRuntimeMode `gorm:"type:int;not null;default:1;index"` // RuntimeMode 为 Agent 执行模式,如内置 Graph 或发布的会话流程。
WorkflowVersionID int64 `gorm:"type:bigint;not null;default:0;index"` // WorkflowVersionID 为绑定的已发布会话流程版本ID。
SortNo int `gorm:"type:int;not null;default:0;index"` // SortNo 为后台展示排序号。
AuditFields
diff --git a/internal/pkg/dto/response/ai_response.go b/internal/pkg/dto/response/ai_response.go
index b1764cc..cc7ca62 100644
--- a/internal/pkg/dto/response/ai_response.go
+++ b/internal/pkg/dto/response/ai_response.go
@@ -91,8 +91,6 @@ type AIAgentResponse struct {
Skills []AIAgentSkillResponse `json:"skills"`
DirectTools []AIAgentMCPToolResponse `json:"directTools"`
GraphTools []string `json:"graphTools"`
- RuntimeMode enums.AIAgentRuntimeMode `json:"runtimeMode"`
- RuntimeModeName string `json:"runtimeModeName"`
WorkflowVersionID int64 `json:"workflowVersionId"`
SortNo int `json:"sortNo"`
CreatedAt string `json:"createdAt"`
diff --git a/internal/pkg/enums/ai.go b/internal/pkg/enums/ai.go
index c17d7d5..3f9ffd3 100644
--- a/internal/pkg/enums/ai.go
+++ b/internal/pkg/enums/ai.go
@@ -31,24 +31,3 @@ var aiModelTypeLabelMap = map[AIModelType]string{
func GetAIModelTypeLabel(modelType AIModelType) string {
return aiModelTypeLabelMap[modelType]
}
-
-type AIAgentRuntimeMode int
-
-const (
- AIAgentRuntimeModeBuiltinGraph AIAgentRuntimeMode = 1
- AIAgentRuntimeModeWorkflow AIAgentRuntimeMode = 2
-)
-
-var AIAgentRuntimeModeValues = []AIAgentRuntimeMode{
- AIAgentRuntimeModeBuiltinGraph,
- AIAgentRuntimeModeWorkflow,
-}
-
-var aiAgentRuntimeModeLabelMap = map[AIAgentRuntimeMode]string{
- AIAgentRuntimeModeBuiltinGraph: "内置 Graph",
- AIAgentRuntimeModeWorkflow: "会话流程",
-}
-
-func GetAIAgentRuntimeModeLabel(mode AIAgentRuntimeMode) string {
- return aiAgentRuntimeModeLabelMap[mode]
-}
diff --git a/internal/services/ai_agent_service.go b/internal/services/ai_agent_service.go
index 4da0f42..0eaf602 100644
--- a/internal/services/ai_agent_service.go
+++ b/internal/services/ai_agent_service.go
@@ -229,7 +229,6 @@ func (s *aIAgentService) buildAIAgentModel(id int64, req request.CreateAIAgentRe
SkillIDs: utils.JoinInt64s(skillIDs),
AllowedMCPTools: directToolsJSON,
AllowedGraphTools: graphToolsJSON,
- RuntimeMode: enums.AIAgentRuntimeModeBuiltinGraph,
WorkflowVersionID: 0,
}, nil
}
@@ -357,26 +356,6 @@ func (s *aIAgentService) normalizeGraphTools(input []string) ([]string, error) {
return ret, nil
}
-func (s *aIAgentService) normalizeRuntimeMode(input enums.AIAgentRuntimeMode, workflowVersionID int64) (enums.AIAgentRuntimeMode, int64, error) {
- if input == 0 {
- input = enums.AIAgentRuntimeModeBuiltinGraph
- }
- if !slices.Contains(enums.AIAgentRuntimeModeValues, input) {
- return 0, 0, errorsx.InvalidParam("invalid ai agent runtime mode")
- }
- if input != enums.AIAgentRuntimeModeWorkflow {
- return input, 0, nil
- }
- if workflowVersionID <= 0 {
- return 0, 0, errorsx.InvalidParam("workflow version is required")
- }
- version := AIWorkflowService.GetVersion(workflowVersionID)
- if version == nil || version.Status != enums.StatusOk {
- return 0, 0, errorsx.InvalidParam("workflow version does not exist")
- }
- return input, workflowVersionID, nil
-}
-
func (s *aIAgentService) UpdateSort(ids []int64) error {
return sqls.WithTransaction(func(ctx *sqls.TxContext) error {
for i, id := range ids {
diff --git a/internal/services/ai_agent_workflow_service_test.go b/internal/services/ai_agent_workflow_service_test.go
index 47a4c3d..e52b983 100644
--- a/internal/services/ai_agent_workflow_service_test.go
+++ b/internal/services/ai_agent_workflow_service_test.go
@@ -99,9 +99,6 @@ func TestAIWorkflowServicePublishAgentWorkflowBindsAgentVersion(t *testing.T) {
if storedAgent == nil {
t.Fatalf("expected stored agent")
}
- if storedAgent.RuntimeMode != enums.AIAgentRuntimeModeWorkflow {
- t.Fatalf("expected agent runtime workflow, got %d", storedAgent.RuntimeMode)
- }
if storedAgent.WorkflowVersionID != version.ID {
t.Fatalf("expected agent workflow version %d, got %d", version.ID, storedAgent.WorkflowVersionID)
}
diff --git a/internal/services/ai_workflow_service.go b/internal/services/ai_workflow_service.go
index da268a9..3771b7f 100644
--- a/internal/services/ai_workflow_service.go
+++ b/internal/services/ai_workflow_service.go
@@ -301,7 +301,6 @@ func (s *aiWorkflowService) PublishAgentWorkflow(req request.PublishAIWorkflowRe
return err
}
return repositories.AIAgentRepository.Updates(ctx.Tx, req.AgentID, map[string]any{
- "runtime_mode": enums.AIAgentRuntimeModeWorkflow,
"workflow_version_id": version.ID,
"update_user_id": operator.UserID,
"update_user_name": operator.Username,
diff --git a/web/app/dashboard/ai-agents/_components/config-workbench.tsx b/web/app/dashboard/ai-agents/_components/config-workbench.tsx
index ca63476..acfeb42 100644
--- a/web/app/dashboard/ai-agents/_components/config-workbench.tsx
+++ b/web/app/dashboard/ai-agents/_components/config-workbench.tsx
@@ -836,10 +836,6 @@ export function AIAgentConfigWorkbench({
Agent 状态