Skip to content

[Platform] Add Endpoint value object and expose it on Model#2235

Open
tacman wants to merge 1 commit into
symfony:mainfrom
tacman:platform-model-endpoints
Open

[Platform] Add Endpoint value object and expose it on Model#2235
tacman wants to merge 1 commit into
symfony:mainfrom
tacman:platform-model-endpoints

Conversation

@tacman

@tacman tacman commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
Q A
Bug fix? no
New feature? yes
Docs? no
Issues -
License MIT

This carves out slice 1 of @chr-hertel's endpoint refactor (#2029) as a small, self-contained, backward-compatible PR — the piece that PR explicitly marks as landable on its own:

1. Endpoint as a first-class concept on Model

  • New Endpoint value object (contract identifier + defaults).
  • Model gains getEndpoints(), getDefaultEndpoint(), getEndpoint(string), supportsEndpoint(string).
  • Catalogs declare endpoints via the new AbstractModelCatalog::endpointsForModel() hook.
  • Minimum viable PR: just the new types + the hook, no consumer changes. Backward-compatible; later PRs migrate consumers.

The intent is to let the Endpoint shape land and be iterated on now (it's also what batch routing — #1802 — and multi-contract models like OpenAI chat-completions vs. responses would hang off of), independently of the larger dispatch rework.

What's here

Endpoint — a value object identifying one contract a model speaks, plus optional contract-specific defaults:

namespace Symfony\AI\Platform;

final class Endpoint
{
    public function __construct(private readonly string $contract, private readonly array $defaults = []) { /* … */ }
    public function getContract(): string;
    public function getDefaults(): array;
}

Model — a new optional, last constructor parameter array $endpoints = [], and five accessors:

$model->getEndpoints();         // Endpoint[]
$model->hasEndpoints();         // bool
$model->getDefaultEndpoint();   // ?Endpoint — the first declared
$model->getEndpoint('openai.responses');     // Endpoint, throws if unsupported
$model->supportsEndpoint('openai.responses'); // bool

AbstractModelCatalog — a new endpointsForModel(array $modelConfig): array hook (defaults to []), called in getModel() and forwarded to the Model constructor, so a catalog can declare a model's endpoints by overriding one method.

Backward compatibility

Fully additive:

  • the new Model constructor parameter is optional and last;
  • the catalog hook defaults to no endpoints, so existing catalogs produce identical models;
  • no consumer or bridge is changed — models without endpoints behave exactly as today.

(Bridge Model subclasses with custom constructors — Anthropic\Claude, the OpenAI/Scaleway Embeddings — keep working unchanged; they'll opt into forwarding $endpoints if and when a catalog starts declaring endpoints for them, in a follow-up.)

Tests

EndpointTest (construction, defaults, empty-contract guard), ModelTest (all five accessors incl. default-is-first and the unsupported-contract exception), and AbstractModelCatalogTest (default = no endpoints; the hook populates a model's endpoints). Full Platform suite green; PHPStan and CS-Fixer clean.

The Endpoint API here matches #2029 verbatim so it drops straight into that branch's later slices.

@carsonbot carsonbot added Feature New feature Platform Issues & PRs about the AI Platform component Status: Needs Review labels Jun 24, 2026
Comment thread src/platform/src/Endpoint.php
Introduces an `Endpoint` value object (a contract identifier the model
speaks, e.g. "openai.chat_completions" / "openai.responses", plus optional
contract-specific defaults) as a first-class concept on `Model`.

`Model` gains `getEndpoints()`, `hasEndpoints()`, `getDefaultEndpoint()`
(the first declared endpoint), `getEndpoint()` and `supportsEndpoint()`.
Catalogs declare a model's endpoints via the new
`AbstractModelCatalog::endpointsForModel()` hook, which defaults to none.

This is purely additive and backward-compatible: the new constructor
parameter is optional and last, the hook defaults to `[]`, and no consumer
or bridge is changed — models without endpoints behave exactly as before.

This is slice 1 of the endpoint refactor sketched in symfony#2029, carved out as a
small, BC-safe PR so the `Endpoint` concept can land and be iterated on
independently of the larger dispatch rework.
@tacman tacman force-pushed the platform-model-endpoints branch from 6d226cc to dc62d37 Compare June 25, 2026 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature New feature Platform Issues & PRs about the AI Platform component Status: Needs Review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants