Skip to content

Plumb EnableMessageInjection through provider AgentConfig so the message-injector loop is reachable - #652

Open
PratikDhanave (PratikDhanave) wants to merge 2 commits into
microsoft:mainfrom
PratikDhanaveFork:plumb-enable-message-injection
Open

Plumb EnableMessageInjection through provider AgentConfig so the message-injector loop is reachable#652
PratikDhanave (PratikDhanave) wants to merge 2 commits into
microsoft:mainfrom
PratikDhanaveFork:plumb-enable-message-injection

Conversation

@PratikDhanave

Copy link
Copy Markdown
Contributor

What

The toolautocall harness already fully implements Config.EnableMessageInjection and its MessageInjector loop (inject.go, wired in autocall.go, tested in autocall_inject_test.go, ported from .NET's MessageInjectingChatClient). However, no provider ever wired the flag: every provider built toolautocall.Config with only Logger/LogSensitiveData, so the message-injector loop was unreachable through the normal agent API.

This PR:

  • Adds EnableMessageInjection bool to agent.Config (in agent/agent.go), beside the existing DisableFuncAutoCall.
  • Passes EnableMessageInjection: config.EnableMessageInjection into each provider's guarded toolautocall.New(toolautocall.Config{...}) literal: openaiprovider (chat + responses), anthropicprovider, geminiprovider, and aguiprovider.

Because each provider AgentConfig embeds agent.Config and forwards config.Config to agent.New, the new field flows to all providers uniformly. Previously the only way to enable injection was DisableFuncAutoCall=true plus hand-rebuilding the middleware, which loses provider defaults.

Why (parity)

This mirrors the .NET MessageInjectingChatClient / EnqueueMessages surface, which is composable into the standard function-invocation pipeline. Exposing the flag on AgentConfig keeps the Go SDK aligned: tools can enqueue follow-up messages into the auto-call loop without opting out of the provider-managed middleware.

Behavior change

None when the field is false (the default). The value is zero-valued for all existing callers, so the installed middleware behaves exactly as before.

Tests

Added two black-box tests in the canonical provider/openaiprovider/chat_test.go:

  • TestChatMessageInjection_ToolInjectsMessage: builds an agent with AgentConfig.EnableMessageInjection=true and a tool that calls MessageInjectorFromContext(ctx).EnqueueMessages(...); asserts the injected message is forwarded to the provider on the following service round and the final answer is produced. This test fails before the wiring change and passes after.
  • TestChatMessageInjection_DisabledReturnsNilInjector: negative case with the field false, asserting MessageInjectorFromContext returns nil and nothing is injected.

go build ./..., go vet, and go test (incl. -race on the new tests) pass for the changed packages.

Open design questions

  • Scope: This threads the existing harness flag through all five providers for consistency. Should the responses/agui paths be excluded if they are considered out of scope for the initial cut?
  • API shape: EnableMessageInjection sits on agent.Config alongside DisableFuncAutoCall. Is that the desired home, or should message injection be surfaced as part of a broader composable-middleware config (cf. Add composable function-invocation middleware to the tool autocall loop #638)?
  • Follow-ups: Only the injector enable flag is plumbed; other toolautocall.Config knobs (e.g. AllowConcurrentInvocations, MaximumIterationsPerRequest) remain provider-internal. Happy to plumb those in a follow-up if that is the direction.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot added the parity-approved Go API consistency review found no parity issues label Jul 23, 2026
@github-actions github-actions Bot added the public-api-change Pull Request changes public APIs label Jul 24, 2026
@github-actions

This comment has been minimized.

The toolautocall harness fully implements Config.EnableMessageInjection
and its MessageInjector loop, but no provider wired the flag: every
provider built toolautocall.Config with only Logger/LogSensitiveData, so
the message-injector loop was unreachable through the normal agent API.

Add EnableMessageInjection to agent.Config beside DisableFuncAutoCall and
pass it into each provider's guarded toolautocall.New literal (openai
chat and responses, anthropic, gemini, agui). The value threads through
the embedded agent.Config on every provider AgentConfig. Behavior is
unchanged when the field is false (the default).
@github-actions

This comment has been minimized.

# Conflicts:
#	provider/openaiprovider/chat_test.go
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Go API Consistency Review — Parity Approved ✅

Summary

This PR plumbs EnableMessageInjection bool from agent.Config through all five provider constructors into toolautocall.Config. The review finds no cross-repo parity issues.


Upstream Alignment

Feature Go (this PR) .NET Python
Flag name agent.Config.EnableMessageInjection ChatClientAgentOptions.EnableMessageInjection Agent(..., middleware=[MessageInjectionMiddleware()])
Default false false opt-in middleware
Scope per-agent config per-agent options per-agent constructor arg
Behavior when disabled nil injector, no loop change no MessageInjectingChatClient in pipeline no middleware present

Semantic equivalence is preserved. All three SDKs gate the feature with an opt-in flag and keep baseline behavior identical when the flag is absent.

  • .NET reference: dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgentOptions.cs (EnableMessageInjection), MessageInjectingChatClient.cs
  • Python reference: python/samples/02-agents/middleware/message_injection_middleware.py, MessageInjectionMiddleware in agent_framework

Minor Observation — Example Coverage Gap

Both upstream SDKs ship a runnable message-injection sample:

  • Python: python/samples/02-agents/middleware/message_injection_middleware.py
  • .NET: dotnet/samples/02-agents/Harness/ (harness-level samples)

Go examples/02-agents/agents/ currently has no equivalent step*_message_injection example. This is not a blocking parity issue for this PR (the feature is tested via chat_test.go), but a follow-up example would complete the sample-parity picture. Tracking as a non-blocking suggestion.


Label Status

  • public-api-change — correct: agent.Config.EnableMessageInjection is an exported field addition
  • parity-approved — set: no semantic divergence found

Generated by Go API Consistency Review Agent · sonnet46 · 32.7 AIC · ⌖ 5.76 AIC · ⊞ 5.7K ·

@PratikDhanave
PratikDhanave (PratikDhanave) marked this pull request as ready for review August 4, 2026 06:06
@PratikDhanave
PratikDhanave (PratikDhanave) requested a review from a team as a code owner August 4, 2026 06:06
Copilot AI lite review requested due to automatic review settings August 4, 2026 06:06

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 makes the existing toolautocall message-injection loop reachable through the normal provider agent constructors by plumbing an EnableMessageInjection flag through agent.Config and into each provider’s toolautocall.Config.

Changes:

  • Added EnableMessageInjection bool to agent.Config so providers can expose message injection via their embedded agent.Config.
  • Threaded EnableMessageInjection into the provider-installed toolautocall.New(toolautocall.Config{...}) middleware across OpenAI (chat + responses), Anthropic, Gemini, and AGUI providers.
  • Added OpenAI chat black-box tests validating injection-enabled behavior and the default disabled behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
agent/agent.go Adds Config.EnableMessageInjection (public surface) and documents intended behavior.
provider/openaiprovider/chat.go Passes EnableMessageInjection into the OpenAI chat agent’s toolautocall middleware config.
provider/openaiprovider/responses.go Passes EnableMessageInjection into the OpenAI responses agent’s toolautocall middleware config.
provider/openaiprovider/chat_test.go Adds end-to-end tests proving injected messages are forwarded on the next provider call (and nil injector when disabled).
provider/anthropicprovider/agent.go Threads EnableMessageInjection into Anthropic provider toolautocall config.
provider/geminiprovider/agent.go Threads EnableMessageInjection into Gemini provider toolautocall config.
provider/aguiprovider/agui.go Threads EnableMessageInjection into AGUI provider toolautocall config.

Comment thread agent/agent.go
Comment on lines +80 to +84
// EnableMessageInjection lets tool implementations enqueue additional messages into the
// automatic function-call loop via the injector returned by
// [github.com/microsoft/agent-framework-go/agent/harness/toolautocall.MessageInjectorFromContext].
// It is threaded into the provider-installed toolautocall middleware and has no effect when
// DisableFuncAutoCall is true.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parity-approved Go API consistency review found no parity issues public-api-change Pull Request changes public APIs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants