Skip to content

todo: migrate tool output to structured JSON schemas#2045

Merged
trungutt merged 1 commit intodocker:mainfrom
dgageot:board/are-the-tools-in-the-todo-toolsets-all-u-1fe09cf0
Mar 11, 2026
Merged

todo: migrate tool output to structured JSON schemas#2045
trungutt merged 1 commit intodocker:mainfrom
dgageot:board/are-the-tools-in-the-todo-toolsets-all-u-1fe09cf0

Conversation

@dgageot
Copy link
Member

@dgageot dgageot commented Mar 10, 2026

Replace plain-text string output with proper JSON-structured responses for all todo tools. Each tool now has a typed OutputSchema matching its actual output:

  • create_todo: returns a Todo object
  • create_todos: returns CreateTodosOutput with created []Todo
  • update_todos: returns UpdateTodosOutput with updated/not_found
  • list_todos: returns ListTodosOutput with todos []Todo

Other improvements

  • Extract addTodo helper to deduplicate todo creation logic
  • Extract jsonResult helper to deduplicate JSON marshaling + ToolCallResult construction
  • Reuse Todo type as create_todo output (eliminates redundant CreateTodoOutput struct)
  • Fix jsonschema descriptions for consistency ("New status" → "Status of the todo item", add missing space)
  • Refactor updateTodos error path to reuse jsonResult instead of duplicating marshal logic
  • Add requireMeta test helper to reduce assertion boilerplate

Replace plain-text string output with proper JSON-structured responses
for all todo tools. Each tool now has a typed OutputSchema matching its
actual output:

- create_todo: returns a Todo object
- create_todos: returns CreateTodosOutput with created []Todo
- update_todos: returns UpdateTodosOutput with updated/not_found
- list_todos: returns ListTodosOutput with todos []Todo

Extract addTodo and jsonResult helpers to reduce duplication.
Fix jsonschema descriptions for consistency.

Assisted-By: docker-agent
@dgageot dgageot requested a review from a team as a code owner March 10, 2026 17:35
Copy link

@docker-agent docker-agent bot left a comment

Choose a reason for hiding this comment

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

🔍 cagent Review

Assessment: 🟢 APPROVE

The refactoring successfully migrates todo tool output to structured JSON schemas with proper error handling and helper function extraction. No critical or high-severity bugs were found.

One minor design inconsistency was noted for consideration:


Optional Improvement

While not blocking, there's a pattern inconsistency in the output structure design:

createTodo returns bare Todo while other tools use wrapper types

  • createTodo returns: Todo directly
  • createTodos returns: CreateTodosOutput{Created: []Todo}
  • updateTodos returns: UpdateTodosOutput{...}
  • listTodos returns: ListTodosOutput{...}

Since this PR explicitly aims for "proper JSON-structured responses," consider wrapping createTodo's output in a dedicated type (e.g., CreateTodoOutput{Todo: Todo}) for consistency with the other tools.

The current implementation works correctly and tests pass—this is purely about maintaining a consistent pattern across all tool outputs.

})
}
func (h *todoHandler) createTodo(_ context.Context, params CreateTodoArgs) (*tools.ToolCallResult, error) {
return h.jsonResult(h.addTodo(params.Description))
Copy link

Choose a reason for hiding this comment

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

Optional Improvement: Output Structure Consistency

The createTodo function returns a bare Todo object, while all other tools wrap their outputs in dedicated types:

  • createTodosCreateTodosOutput{Created: []Todo}
  • updateTodosUpdateTodosOutput{...}
  • listTodosListTodosOutput{...}
  • ⚠️ createTodoTodo (bare object)

Since this PR explicitly refactors for "proper JSON-structured responses," consider wrapping this output in a dedicated type (e.g., CreateTodoOutput{Todo: Todo}) for consistency.

Not blocking—the current implementation works correctly.

@dgageot dgageot marked this pull request as draft March 10, 2026 19:58
@dgageot dgageot marked this pull request as ready for review March 11, 2026 09:17
Copy link

@docker-agent docker-agent bot left a comment

Choose a reason for hiding this comment

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

Review Summary

Assessment: 🟡 NEEDS ATTENTION

The migration to structured JSON schemas is well-executed with proper helper functions. However, there is a logic bug in the updateTodos function where the auto-clear mechanism can trigger even when some updates fail with NotFound errors.

Critical Issues

None

Notable Issues

  1. Auto-clear triggers on partial failures (pkg/tools/builtin/todo.go:236)
    • The storage auto-clear can execute even when some todo updates fail with NotFound errors, which is inconsistent behavior

Summary

The refactoring successfully introduces type-safe JSON schemas for all todo tool outputs and reduces code duplication through helper functions. The identified issue should be addressed to ensure auto-clear only happens when ALL requested updates succeed.

return res, nil
}

if h.allCompleted() {
Copy link

Choose a reason for hiding this comment

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

MEDIUM: Auto-clear triggers even when some updates fail

The allCompleted() check executes even when len(result.NotFound) > 0, meaning some updates failed. This can cause storage to be cleared after a partially failed operation.

Example scenario:

  • You have 2 existing todos, both already marked as completed
  • You attempt to update all 3 todos (including a non-existent one) to completed
  • Result: 2 updated successfully, 1 NotFound
  • Bug: The code skips the error block (because len(result.Updated) > 0), then allCompleted() returns true and clears storage

Impact: A partially failed update operation inappropriately triggers auto-clear behavior.

Recommendation: Only trigger auto-clear when ALL requested updates succeeded:

if len(result.NotFound) == 0 && h.allCompleted() {
    h.storage.Clear()
}

@trungutt trungutt merged commit 27ee4cd into docker:main Mar 11, 2026
11 checks passed
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