WordPress / WordPress/php-ai-client

Allow providers to prepare function declarations before tool-calling requests

Open
#256 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
308
Forks
84
Avg merge
7d 21h
Merged PRs (30d)
2

Description

Context

This came out of the WordPress Core discussion in https://core.trac.wordpress.org/ticket/64955.

The original Core ticket explored compiling Abilities API schemas for AI/tool-calling compatibility. After tracing the flow more closely, the part that matters for tool calling is the input schema exposed as FunctionDeclaration::parameters.

The LLM only receives the tool declaration and generates a tool call with arguments. The actual tool execution happens later outside the model, so ability output schemas / structured response schemas are not part of this compatibility problem.

Current behavior

Today, function declarations are serialized into the provider request as-is. For OpenAI-compatible models, AbstractOpenAiCompatibleTextGenerationModel::prepareToolsParam() effectively does:

$tools[] = array(
    'type'     => 'function',
    'function' => $functionDeclaration->toArray(),
);

That means provider-specific JSON Schema compatibility rules cannot be handled by the provider model before the request is sent.

Different providers support different subsets or variants of JSON Schema for tool input schemas. For example, a provider may need to normalize or remove unsupported schema keywords, adjust object schemas, rewrite composition keywords, or otherwise prepare the schema used in parameters.

Proposal

Add a protected no-op method that provider models can override before a function declaration is serialized for a tool-calling request:

protected function prepareFunctionDeclarationForRequest(
    FunctionDeclaration $functionDeclaration
): FunctionDeclaration {
    return $functionDeclaration;
}

Then call it from prepareToolsParam():

protected function prepareToolsParam( array $functionDeclarations ): array {
    $tools = array();

    foreach ( $functionDeclarations as $functionDeclaration ) {
        $functionDeclaration = $this->prepareFunctionDeclarationForRequest( $functionDeclaration );

        $tools[] = array(
            'type'     => 'function',
            'function' => $functionDeclaration->toArray(),
        );
    }

    return $tools;
}

The default implementation would preserve current behavior exactly. Providers that need custom compatibility handling could return either the original declaration or a new FunctionDeclaration with adjusted name, description, or parameters.

Example override:

protected function prepareFunctionDeclarationForRequest(
    FunctionDeclaration $functionDeclaration
): FunctionDeclaration {
    return new FunctionDeclaration(
        $functionDeclaration->getName(),
        $functionDeclaration->getDescription(),
        $this->prepareToolInputSchemaForRequest( $functionDeclaration->getParameters() )
    );
}

Why provider-level?

This seems like a provider/model request-serialization concern rather than a WordPress Core schema compiler concern. The canonical schema can remain unchanged, while each provider decides whether and how to adapt tool input schemas for its own API.

Out of scope

This issue is only about function declarations / tool input schemas.

Structured output schemas and response_format handling are separate concerns and do not need to be changed for Abilities API tool calling compatibility.

Suggested tests

  • Default implementation preserves the current tools payload.
  • A provider model overriding prepareFunctionDeclarationForRequest() can change parameters before serialization.
  • A provider model overriding the method can return the same declaration unchanged.
  • Function declarations without parameters continue to serialize as they do today.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at AbstractOpenAiCompatibleTextGenerationModel::prepareToolsParam() and trace how FunctionDeclaration objects become the tools payload. Add coverage for the default behavior, provider overrides that change or preserve parameters, and declarations without parameters; done means the current payload remains unchanged by default while overrides are serialized before the request.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
api, backend-api-design
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.