Bound and instrument large plugin tool-result payloads in chat turns
Los mantenedores suelen responder en 1 día
@paullizer ya está trabajando en esto.
Desde el 20/8/2026.
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Summary
Plugin (action) tool results are retained and passed around a chat turn without a shared size bound, and we have no diagnostics that would let us distinguish a memory problem from a Cosmos write problem from a model context-window problem.
A customer running Simple Chat locally reports the app crashing when an action returning large result sets is combined with an Azure AI Search workspace. We cannot currently diagnose that from logs, because nothing reports how much data a turn actually accumulated or where it went.
Add size instrumentation first so the failure mode can be identified, then apply a shared bounding policy for plugin results. This is not specific to any one action type.
User Value
- Admins and developers can see why a chat turn failed instead of getting an opaque crash or a generic error.
- Actions that legitimately return large datasets degrade predictably instead of taking down the process.
- Removes the need for each action type to invent its own limits, which is the current situation and is inconsistent.
Proposed Behavior
Phase 1 — Diagnostics
Instrument with debug_print / log_event:
- Serialized byte size of each plugin invocation result, attributed to plugin and function name.
- Cumulative tool-result bytes accumulated for the current turn.
- Total retained size of
PluginInvocationLogger.invocationsafter each append, not just the item count. - Assembled prompt payload size immediately before the model call, broken down by conversation history, document/search citations, and tool results.
- Explicit classification of Azure OpenAI
400responses, distinguishingcontext_length_exceededfrom other bad requests.
Phase 2 — Shared bounding policy
- A single configurable cap for plugin tool-result payloads, applied consistently rather than per action type.
- Bound what is retained in memory, not only what is logged or persisted.
- Surface truncation explicitly to the model and to the user, so a truncated result is never silently presented as complete.
Acceptance Criteria
- Per-invocation and per-turn tool-result sizes appear in debug logging with plugin and function attribution.
- Retained invocation-history size is observable and bounded by bytes, not only by item count.
- Prompt assembly logs a size breakdown before the model call.
- Azure OpenAI context-length errors are logged distinctly and surfaced as an actionable message rather than a generic failure.
- A shared plugin result cap exists and applies regardless of action type.
- Truncation is explicitly marked in the result handed to the model.
- Functional test covering an oversized plugin result, asserting bounding and truncation signaling.
Notes
Current state
PluginInvocationLogger.__init__(semantic_kernel_plugins/plugin_invocation_logger.pyL343) retainsmax_history = 1000invocations holding the full, untruncatedresultobject. Truncation viasanitize_plugin_invocation_value(max_string_length=500) andMAX_SAFE_INVOCATION_STRING_LENGTH = 20000is applied to logging and persistence output only, never to retained state.get_invocations_for_conversation(..., limit=1000)is called from at least eight sites inroute_backend_chats.pyduring a single turn, including L3000, L3024, L18511, L18874, and L19418.- Per-action-type limits exist and are inconsistent:
MCP_MAX_TOOL_RESULT_TEXT_LENGTH = 120000infunctions_mcp_operations.py; the Yamcs action defaults tomax_rows = 500andbyte_limit = 250000; several other action types have no cap at all. - Search contributes independently:
SEARCH_DEFAULT_TOP_N = 12andSEARCH_MAX_TOP_N = 500infunctions_search.py. conversation_history_limit(default 10) replays prior messages, which may already carry large tool payloads from earlier turns.
Pattern to reuse
build_evidence_envelope in functions_mixed_source_orchestration.py L1121 already implements bounded JSON lists and UTF-8-safe truncation with an explicit bounds_applied flag. That is the shape the shared policy should follow rather than inventing a new one.
Leading hypothesis
Process memory exhaustion from retained full-size invocation results, not model context overflow. A context overflow would return a clean Azure OpenAI 400, which the customer is not seeing. Retaining up to 1000 full results and re-reading them from many call sites per turn is the mechanism that scales badly. This is masked in App Service by gunicorn worker recycling and available RAM, and manifests as a hard process exit on a developer workstation running other workloads alongside it.
Secondary candidates to confirm or eliminate with the same instrumentation, rather than assume:
- Cosmos DB 2 MB item size limit on message save when citations carry large tool results. The
log_tool_executionpath inagent_logging_chat_completion.pyL39 truncatesfunction_resultto 500 characters, but citations built from the invocation logger take a different path that needs verifying. - Repeated deep copy and serialization of large results across the sanitize → citation → persist chain.
- The Werkzeug development server with
threaded=Truebeing less resilient under memory pressure than gunicorn.
Related gap
route_backend_chats.py L14291 is the only place that pattern-matches BadRequestError, and it does not distinguish context-length failures. If the model is reporting an oversized prompt, we are currently discarding that signal.
Staging
Phase 1 is independently valuable and should ship first. Phase 2 should not be scoped until Phase 1 data identifies the actual failure mode.
- Lenguaje dominante
- Python
- Estrellas
- 157
- Forks
- 117
- Merge medio
- 3 h 31 min
- PR fusionados (30 d)
- 226
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de microsoft/simplechat
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
microsoft/simplechat#1491 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
microsoft/simplechat#1370 ·
Los mantenedores suelen responder en 1 día
-
Add conversation references and queued AI handoffs across chat, orchestration, and workflowsPosiblemente ocupada @paullizer la tomó hace 3 días. AbiertoCreated By Copilot enhancement P2
microsoft/simplechat#1835 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Stale activeGroupOid after group removal interrupts chat in legacy and React V2Posiblemente ocupada @paullizer la tomó hace 5 días. Abiertobug P1
microsoft/simplechat#1816 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Simple Chat - NLRAbierto
Dificultad 3/5 1-2 días Aptitud para principiantes 55/100
microsoft/simplechat#1804 ·
Los mantenedores suelen responder en 1 día
Todos los issues de microsoft/simplechat
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
sylvainmetayer/homelab#851 ·
Los mantenedores suelen responder en 1 día
-
needs triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
-
Add `ty-pre-commit` hookAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
kubeflow/docs-agent#279 ·
Los mantenedores suelen responder en 3 días
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 67/100
Qiskit/qiskit-ibm-runtime#3523 ·
Los mantenedores suelen responder en 1 día