Skip to content

Latest commit

 

History

History
111 lines (72 loc) · 4.66 KB

File metadata and controls

111 lines (72 loc) · 4.66 KB

ADR-006: Inline tool definition with lambdas

Context and problem statement

ADR-005 introduced an ergonomic Java tools API based on @CopilotTool, @CopilotToolParam, and ToolDefinition.fromObject(...). That model works well when teams define tools as methods on a class.

The next ergonomics goal is an inline style comparable to C# CopilotTool.DefineTool(...), where developers can define a tool at the call site without creating a separate tool container class.

For this decision, we evaluated two alternatives:

  • Method-reference registration (ToolDefinition.from(tools::setCurrentPhase))
  • Inline lambda registration (ToolDefinition.from(..., phase -> ...))

The key factor is metadata quality: tool name, description, parameter names, parameter descriptions, required/default semantics, and schema stability.

Considered options

Option 1: Method-reference API

Example:

ToolDefinition setPhase = ToolDefinition.from(tools::setCurrentPhase);

In this model, metadata is sourced from existing method-level annotations (@CopilotTool, @Param) on the referenced method.

Advantages:

  • Closest Java analog to C# method-group ergonomics
  • High-quality metadata with minimal additional API surface
  • Reuses ADR-005 metadata and invocation behavior directly

Drawbacks:

  • Not truly inline: still requires a declared method (and usually annotations) elsewhere
  • Does not solve the "define the whole tool at the call site" use case
  • Method-reference resolution adds runtime/reflection complexity

Option 2: Inline lambda API with explicit metadata

Example:

ToolDefinition setPhase = ToolDefinition.from(
        "set_current_phase",
        "Sets the current phase of the agent",
        Param.of(String.class, "phase", "The phase to transition to"),
        phase -> {
            currentPhase = phase;
            return "Phase set to " + phase;
        });

In this model, handler logic is inline, and metadata is provided explicitly through a small parameter-definition DSL.

Advantages:

  • True inline authoring at the session construction site
  • No dependence on lambda parameter-name reflection or -parameters
  • Deterministic metadata and schema generation
  • Independent from annotation processing and generated companion classes

Drawbacks:

  • Slightly more verbose than method-reference style because metadata is explicit
  • Introduces new public API types for parameter definitions and typed lambda overloads
  • Requires careful API design to stay concise for common one-parameter tools

Decision outcome

Chosen: Option 2 for ADR-006 scope — inline lambda API with explicit metadata.

Rationale:

  1. The primary requirement for this ADR is inline definition. Option 2 satisfies it directly; Option 1 does not.
  2. Metadata quality is the critical requirement. Option 2 keeps metadata explicit and stable, instead of relying on fragile lambda introspection.
  3. Option 2 can ship independently of method-reference support and without changes to annotation processing.
  4. Option 2 preserves behavior parity with existing tool execution by delegating to ToolDefinition construction and current invocation semantics.

Option 1 remains valuable and can be added independently as a separate ergonomic layer. It is not blocked by this decision.

Design constraints and non-goals

Constraints for the inline lambda API:

  • Require explicit tool name and description.
  • Require explicit parameter metadata (at minimum name and type, with optional description/required/default).
  • Support both sync and async handlers (R and CompletableFuture<R>).
  • Keep result semantics aligned with existing behavior (String passthrough, void maps to "Success", non-string objects serialized to JSON).
  • Keep override/permission/defer flags available through options, consistent with existing ToolDefinition fields.

Non-goals for this ADR:

  • Replacing @CopilotTool/fromObject APIs.
  • Defining method-reference registration behavior in detail.
  • Introducing compile-time code generation for lambda metadata.

Consequences

If implemented, the SDK gains an explicit inline path for developers who prefer to keep tool declarations at session creation while preserving high-quality schema metadata.

The annotation-driven API from ADR-005 remains the recommended path for larger tool surfaces where co-locating metadata with method implementations improves maintainability.

The Java README now includes concise examples for ToolDefinition.from(...), fromAsync(...), fromWithToolInvocation(...), and fromAsyncWithToolInvocation(...) using Param<T> required/default behavior and fluent option modifiers.

Related work items

  • #1682
  • #1792
  • #1810