Skip to content

feat: consume cogito for agent reasoning#320

Merged
mudler merged 33 commits into
mainfrom
cogito
Oct 27, 2025
Merged

feat: consume cogito for agent reasoning#320
mudler merged 33 commits into
mainfrom
cogito

Conversation

@mudler

@mudler mudler commented Oct 10, 2025

Copy link
Copy Markdown
Owner

Blocked by: mudler/cogito#9
Depends on : mudler/cogito#13

some TODO:

  • Dropping methods used to extract tools/gaps
  • Write a Action -> cogito.Tool converter
  • Wire MCP servers with cogito.WithMCPs() and pass by MCP client sessions
  • For re-evaluating with goals, we can put that under a flag and use the ContentReview on the resulting fragment of the tool execution loop
  • QA

@mudler mudler linked an issue Oct 10, 2025 that may be closed by this pull request
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Comment thread core/agent/agent.go
obs.Progress = append(obs.Progress, types.Progress{
ActionResult: res.Result,
})
a.observer.Update(*obs)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have lines like this been recreated in the new version?

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
@mudler mudler marked this pull request as ready for review October 19, 2025 19:51
Copilot AI review requested due to automatic review settings October 19, 2025 19:51
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR integrates the Cogito library to drive agent reasoning and tool execution, and removes the legacy “old” web UI in favor of the new React UI.

  • Replace in-house planning/reasoning and MCP tool wrapping with Cogito-based execution and evaluation
  • Remove legacy server-side templates and HTMX-based UI; simplify Fiber app initialization for React UI
  • Add Cogito integration points (status callbacks, tool callbacks, MCP sessions); update knowledgebase summarization to use Cogito

Reviewed Changes

Copilot reviewed 34 out of 37 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
webui/routes.go Removes old embedded views/public routes; keeps React UI assets served.
webui/old/... (multiple) Deletes legacy HTML/CSS/JS views and assets.
webui/app.go Drops HTMX/templates engine usage; simplifies Fiber initialization.
go.mod Adds cogito dependency; updates Go version/toolchain; adjusts deps.
core/types/job.go Removes nextAction/pastActions; adds cogito.Fragment field.
core/types/actions.go Adds cogito wrapper to expose Actions as Cogito tools; removes Plannable from interface.
core/agent/templates.go Simplifies templates to align with Cogito-driven flow.
core/agent/mcp.go Stops generating Actions for MCP tools; keeps MCP client sessions for Cogito.
core/agent/knowledgebase.go Uses Cogito LLM to summarize conversation.
core/agent/evaluation.go Removes custom evaluation; Cogito now handles evaluation.
core/agent/agent.go Major refactor to Cogito execution, planning, and callbacks; cleans old codepaths.
core/agent/actions.go Removes custom decision/planning utilities; simplifies available actions.
core/action/* (several) Removes obsolete actions (reply, reasoning, plan, intention, goal).

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread core/agent/agent.go Outdated
Comment on lines +728 to +739
chosenAction := availableActions.Find(tc.Name)

var obs *types.Observable
if job.Obs != nil {
obs = a.observer.NewObservable()
obs.Name = "action"
obs.Icon = "bolt"
obs.ParentID = job.Obs.ID
obs.Creation = &types.Creation{
FunctionDefinition: chosenAction.Definition().ToFunctionDefinition(),
FunctionParams: types.ActionParams(tc.Arguments),
}

Copilot AI Oct 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible nil pointer dereference if chosenAction is nil (e.g., for MCP tools or tools not in availableActions). Guard chosenAction before accessing Definition() and before later uses (job.Callback, SetResult). If nil, skip FunctionDefinition, and either construct a minimal placeholder for observer/callback or branch handling for non-local tools.

Copilot uses AI. Check for mistakes.
Comment thread core/agent/agent.go
Comment on lines +809 to +825
cont := job.Callback(types.ActionCurrentState{
Job: job,
Action: chosenAction,
Params: types.ActionParams(tc.Arguments),
Reasoning: reasoning})

if !cont {
job.Result.SetResult(
types.ActionState{
ActionCurrentState: types.ActionCurrentState{
Job: job,
Action: chosenAction,
Params: types.ActionParams(tc.Arguments),
Reasoning: reasoning,
},
ActionResult: types.ActionResult{Result: "stopped by callback"},
})

Copilot AI Oct 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same nil dereference risk: chosenAction may be nil for MCP/external tools. Add a nil check and handle callback/result construction accordingly to avoid panics.

Copilot uses AI. Check for mistakes.
Comment thread core/agent/agent.go
Comment on lines +870 to 874
toolToCall := fragment.Messages[len(fragment.Messages)-2].ToolCalls[0].Function.Name
switch toolToCall {
case action.StopActionName:
job.Result.Finish(nil)
return

Copilot AI Oct 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential out-of-bounds access if fragment.Messages has fewer than 2 entries or if the assistant message has no ToolCalls. Guard lengths before indexing and verify ToolCalls is non-empty to avoid panics.

Suggested change
toolToCall := fragment.Messages[len(fragment.Messages)-2].ToolCalls[0].Function.Name
switch toolToCall {
case action.StopActionName:
job.Result.Finish(nil)
return
// Guard against out-of-bounds access
if len(fragment.Messages) >= 2 {
toolCalls := fragment.Messages[len(fragment.Messages)-2].ToolCalls
if len(toolCalls) > 0 {
toolToCall := toolCalls[0].Function.Name
switch toolToCall {
case action.StopActionName:
job.Result.Finish(nil)
return
}
}

Copilot uses AI. Check for mistakes.
fragment := cogito.NewEmptyFragment().AddStartMessage("user", "Summarize the conversation below, keep the highlights as a bullet list:\n"+Messages(conv).String())
fragment, err := a.llm.Ask(a.context.Context, fragment)
if err != nil {
xlog.Error("Error summarizing conversation", "error", err)

Copilot AI Oct 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Ask returns an error, fragment might be nil or incomplete; calling fragment.LastMessage() can panic. Return early on error (or ensure fragment is valid) before accessing LastMessage.

Suggested change
xlog.Error("Error summarizing conversation", "error", err)
xlog.Error("Error summarizing conversation", "error", err)
return

Copilot uses AI. Check for mistakes.
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Comment thread core/agent/agent.go
},
},
},
})

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks quite suspicious. It seems like this is creating and completing an observable for a decision step upon receiving the result of that decision. Really it should be created when the first request is submitted to the LLM as part of the decision process.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm you are right, I think I've did some mistake when porting the logic, can you check again?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to create the observable when making the request to the LLM and close it when you get the result. I don't know if you have the callbacks for this in Cogito? It's the kind of thing only needed for observability.

Presently the user will just see the decision appear after completion with the whole of conv as the query to the LLM which may or may not be what is actually passed to the LLM.

@mudler mudler Oct 21, 2025

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is WithStatusCallback which is called with the reasoning, and WithToolCallResultCallback with the tool call result. WithToolCallBack instead accepts a func with a boolean, which if false will stop the tool execution and the agent.

I think I've misread a bit things initially, but now I've moved the update and the closing of the observable to use the callbacks above

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly there should be WithReasoningCallback and WithReasoningResultCallback?

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Comment thread core/agent/agent.go
Comment thread core/agent/agent.go
Comment thread core/agent/agent.go
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
@mudler mudler force-pushed the cogito branch 11 times, most recently from d0887fd to 38dbaa7 Compare October 24, 2025 19:21
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
@mudler mudler force-pushed the cogito branch 2 times, most recently from 8c2cd2e to e7ba8b5 Compare October 25, 2025 17:37
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
@mudler

mudler commented Oct 25, 2025

Copy link
Copy Markdown
Owner Author

tests are passing and manual tests looks good - the only issues I have now are with the observables @richiejp - looks like these are stuck in progress, but can't really pinpoint what's wrong

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
@mudler mudler force-pushed the cogito branch 3 times, most recently from 06e4d0d to cdabab8 Compare October 27, 2025 16:37
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
@mudler mudler merged commit 73a6be8 into main Oct 27, 2025
2 checks passed
@mudler mudler deleted the cogito branch October 27, 2025 17:41
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.

Consume cogito

3 participants