microsoft / microsoft/agent-framework-go
Expose tool invocation identity through delegating-agent middleware
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 619
- Forks
- 56
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 122
Description
Summary
Expose the current tool invocation identity, including the function call ID, through the delegating-agent middleware design proposed by the maintainers in #638.
This should preserve the idiomatic FuncTool.Call(context.Context, args) API introduced by #205. The goal is not to restore the removed custom tool.Context, but to provide a supported per-invocation interception contract for policy, approval, audit, and gateway integrations.
Motivation
The automatic tool-call loop already has the originating message.FunctionCallContent and uses its CallID to correlate approval requests, function results, and OpenTelemetry spans. However, application middleware and tool wrappers do not currently have a supported public contract for that identity.
Enterprise tool gateways commonly need to bind:
- a policy decision to the exact logical tool call;
- an approval request and its resumed execution;
- normalized argument digests and consume-once records;
- audit events and function results;
- parallel calls to separate correlation records.
Passing this identity as a model-generated tool argument is not appropriate because it mixes framework metadata with model-controlled business arguments.
Existing direction
PR #638 demonstrated the need for per-function interception. It was closed with maintainer guidance that the capability should be implemented as an agent.Middleware that replaces real tools with lifecycle-aware wrappers, similar to the .NET delegating-agent design.
This proposal follows that direction.
Proposed contract
A delegating-agent middleware should be able to observe a per-invocation context containing at least:
- the invoked tool;
- the original function-call content or an explicit
CallID; - the normalized invocation arguments;
- the invocation result or error;
- the current
context.Context.
The exact API shape can follow the wrapper approach preferred in #638. Two possible non-exclusive surfaces are:
- a public function-invocation context passed to the wrapper callback;
- a typed accessor such as
tool.InvocationFromContext(ctx)when the wrappedFuncToolitself needs the metadata.
The second option should keep using standard context.Context; it should not reintroduce a custom context parameter.
Semantics to document
- The call ID identifies one logical tool invocation.
- The same approved invocation should expose the same call ID when execution resumes.
- Parallel invocations must expose distinct IDs.
- Provider behavior when no call ID is supplied should be documented, including whether the framework creates a synthetic ID.
- The call ID is a correlation identifier, not a cross-run idempotency key.
- Authorization must not rely on the call ID alone.
Suggested acceptance tests
- A delegating middleware observes the call ID before invoking a normal tool.
- An approval-required call exposes the same call ID before approval and during approved execution.
- Two parallel calls to the same tool expose distinct call IDs.
- A value added to
context.Contextby the wrapper reachesFuncTool.Call. - With no delegating middleware configured, current tool-call behavior remains unchanged.
- Function results retain the same call ID observed by the middleware.
I would be happy to contribute a focused implementation and tests after the API shape is confirmed.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the agent.Middleware direction from #638 and the existing FuncTool.Call(context.Context, args) contract. Compare the proposed wrapper callback with tool.InvocationFromContext(ctx), then use the six suggested acceptance tests to define the API behavior. Done means call IDs and invocation metadata are observable across normal, approved, parallel, and result-producing calls without changing behavior when middleware is absent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- ai, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100