functool's non-struct input wrapping ({"Arg0": ...}) breaks todo tools for models that don't guess the hidden envelope key
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 52/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- go
- Ambito
- ai, backend-api-design
Direzione di ricerca
Start by reading functool.inputFormatFor and the related change in issue #527 to understand why non-struct inputs are wrapped. Then inspect the todo provider's todos_add, todos_complete, and todos_remove handlers under agent/harness/todo; compare their generated schemas and call behavior with the bare input shapes in this report. Done means the selected fix lets models call these tools using a discoverable input shape, with validation covering the reported cases.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
functool.inputFormatFor wraps any non-struct In type in an undocumented inputWrapper[T]{ Arg0 T } envelope, so the JSON schema exposed to the model for a tool like todos_remove(ids []int) requires {"Arg0": [...]} instead of a bare array. This key is never mentioned in the tool's name, description, or anywhere a model could discover it from context — it only exists because of the Go field name chosen for the wrapper struct.
In practice, several models (confirmed with a local/open model via an OpenAI-compatible endpoint; likely any model that isn't extremely strict about schema adherence) send the natural shape implied by the tool description instead — a bare array — and every call is rejected.
This directly breaks the built-in agent/harness/todo provider's todos_add, todos_complete, and todos_remove tools, which are defined with raw slice handlers:
func(ctx context.Context, input []ItemInput) ([]Item, error) // todos_add
func(ctx context.Context, items []CompleteInput) (int, error) // todos_complete
func(ctx context.Context, ids []int) (int, error) // todos_remove
When a model calls todos_remove with the bare array its own tool description implies, the call fails validation and the model has no way to discover the correct shape short of parsing the raw JSON schema character-by-character. In a real session, this left two todo items permanently stuck as "open" — the model repeatedly tried to mark them complete/remove them, got a rejection every time, and gave up, reporting it as a tool bug (it was right).
Repro
tl := functool.MustNew(
functool.Config{Name: "todos_remove", Description: "remove"},
func(ctx context.Context, ids []int) (int, error) {
return len(ids), nil
},
)
tl.Call(context.Background(), `[1,2]`)
// → validation error: validating root: type: [1 2] has type "array", want "object"
tl.Call(context.Background(), `{"Arg0":[1,2]}`)
// → 2, nil
Confirmed against both v0.3.0 and current main (2cd194d) — unchanged.
Related prior work
#527 ("Do not wrap pointer-to-struct functool inputs") fixed the same inputWrapper/Arg0 mechanism for the *Struct case, but by design left genuinely non-struct inputs (slices, maps, primitives) wrapped exactly as before. This issue is about that remaining case specifically causing real-world tool-call failures, not about removing the wrapping mechanism itself (which is presumably still needed to keep the top-level schema an object for non-struct types).
Suggested fix
A couple of options that don't require removing the wrapping mechanism:
- Give the wrapper field a stable, descriptive JSON name (e.g.
valueoritems) instead of the Go-reflection-derivedArg0, and document it so tool authors know what shape to describe to the model. - For the specific
agent/harness/todoprovider, changetodos_add/todos_complete/todos_removeto accept a small named struct (e.g.type RemoveInput struct { IDs []int }) instead of a raw slice, producing a flat, self-documenting schema ({"ids": [...]}) that doesn't depend on functool's wrapping behavior at all.
Happy to send a PR for option 2 (the todo provider specifically) if that's the preferred direction.
Environment
github.com/microsoft/agent-framework-gov0.3.0 and currentmain- Go 1.25
- Lingua principale
- Go
- Stelle
- 659
- Fork
- 67
- Merge medio
- 14h 51m
- PR unite (30g)
- 81
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di microsoft/agent-framework-go
-
[aw] Upgrade availableApertaagentic-workflows
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
microsoft/agent-framework-go#1350 ·
I maintainer di solito rispondono entro 1 giorno
-
agentic-workflows
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
microsoft/agent-framework-go#1348 ·
I maintainer di solito rispondono entro 1 giorno
-
agentic-workflows
Difficoltà 4/5 3-5 giorni Idoneità per principianti 28/100
microsoft/agent-framework-go#1327 ·
I maintainer di solito rispondono entro 1 giorno
-
Add a reusable workflow for dependency upgrade analysis and fixesForse già presa @michelle-clayton-work l’ha presa 16 giorni fa. Aperta
Difficoltà 5/5 Più di una settimana Idoneità per principianti 15/100
microsoft/agent-framework-go#1287 · 3 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Add a per-run limit for tool callsForse già presa @Lokesh118 l’ha presa 9 giorni fa. Aperta
Difficoltà 3/5 1-2 giorni Idoneità per principianti 67/100
microsoft/agent-framework-go#1202 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di microsoft/agent-framework-go
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
kubeflow/semantic-operator#52 ·
I maintainer di solito rispondono entro 10 giorni
-
enhancement help wanted
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
PramodBasavarajMenasi/siftwise#52 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
dragonflydb/dragonfly-operator#619 ·
I maintainer di solito rispondono entro 2 giorni
-
非流式 /v1/chat/completions 经 Responses 转换时丢失 reasoning_content(vLLM 上游 summary 为空、思考在 content 中)Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 2 giorni
-
lazygit is not RustAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 78/100