Skip to content

Agent package, slice 5: AsAgentTools - #110

Merged
joadan merged 2 commits into
mainfrom
agent-ai-adapter
Oct 15, 2026
Merged

joadan merged 2 commits into
mainfrom
agent-ai-adapter

Conversation

@joadan

@joadan joadan commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Fifth slice of the agent package described in docs/design/agent-mode.md: the public entry point that turns a generated client into agent tools.

IList<AIFunction> tools = client.AsAgentTools(o =>
{
    o.AllowQuery(c => c.Query.Customers).Describe("All customers.");
    o.Omit<Customer>(c => c.Address);
    o.Example("Customer names", "The name and status of every customer",
        c => c.Query.Customers().Select(e => e.Select(x => new { x.CustomerName, x.Status })));
    o.AccessToken = ct => tokens.GetAgentTokenForUserAsync(user, ct);
    o.OnQuery(log => logger.LogInformation("{Query} sent={Sent}", log.Query, log.WasSent));
});

Changes

Client and generator

  • IGraphClientSource<TSelf>, implemented by every generated client: its GraphClient and WithRequestConfiguration. AsAgentTools<TClient> uses it to execute through the client and derive a per-user client of the same type without reflection. Additive: the generated client interface is unchanged. Test clients regenerated (one line each).
  • GetRequest() on typed queries: the request built without contacting the server (safe mode's schema check skipped), used to render examples at setup.

Linq2GraphQL.Client.AI

  • AsAgentTools returns graphql_query, describe_operation, describe_type and search_schema as Microsoft.Extensions.AI AIFunctions, with parameter descriptions; graphql_query carries the Index in its description. It requires a client generated with --agent; an overload takes the SDL explicitly.
  • o.AccessToken: a per-user client via WithAccessToken, so every query the agent causes, raw or typed, carries the user's token.
  • o.OnQuery: every query, sent or rejected, with validation errors, server errors and duration. A failing logger does not break the agent's call.
  • o.Example(...) with typed queries: validated against the scope at setup, listed in the Index, shown in full in describe_operation for the operations they use, found by search_schema. Tidied before the agent sees them: query($name_1_1: String ){ hello(name:$name_1_1 ) } becomes query($name: String) { hello(name: $name) }.
  • New dependency: Microsoft.Extensions.AI.Abstractions 10.10.0, in the AI package only.

Design doc: slice status, IGraphClientSource, GetRequest() and example tidying.

Testing

  • 292 tests pass, 12 new:
    • AgentToolsExtensionsTests calls the tools through AIFunction.InvokeAsync, as an agent framework does: the four tools and their descriptions, queries with variables, describe and search, the bearer token reaching the server, OnQuery for sent and rejected queries, examples in all three places, an example outside the scope failing at setup, the explicit-SDL overload.
    • ExampleFormatterTests: variable renaming, keeping suffixes when plain names would clash, string literals left alone, one-line printing.
  • ./scripts/regenerate-test-clients.ps1 -Check is covered by CI; locked restore succeeds.

IGraphClientSource<TSelf> is implemented by every generated client: its
GraphClient and WithRequestConfiguration. Other packages can then work with
any generated client generically, for example to derive a per-user client of
the same type, without reflection. It is additive; the generated client
interface is unchanged. The test clients are regenerated.

GetRequest() on typed queries builds the request without contacting the
server: safe mode's schema check is skipped. It is meant for showing or
logging a query.
Fifth slice of the agent package (docs/design/agent-mode.md). AsAgentTools on
a client generated with --agent (or with SDL passed explicitly) returns
graphql_query, describe_operation, describe_type and search_schema as
AIFunctions; graphql_query carries the Index in its description.

- AccessToken derives a per-user client, so every query the agent causes,
  raw or typed, carries the user's token.
- OnQuery sees every query, sent or rejected, with validation errors, server
  errors and duration; a failing logger does not break the agent's call.
- Example adds a common task written with the typed client. Examples are
  validated against the scope at setup, listed in the Index, shown in full in
  describe_operation and found by search_schema. Before the agent sees them,
  variables lose the client's uniqueness suffixes where unambiguous and the
  query is printed on one line.

Adds Microsoft.Extensions.AI.Abstractions 10.10.0 to the AI package only.
@joadan
joadan merged commit 2a3394e into main Oct 15, 2026
2 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.

1 participant