Runtime
TypeSafe preset¶
Set TYPESAFE_API_KEY, then use the bundled preset:
use Cognesy\Polyglot\Decision\Decision;
$decision = Decision::using('typesafe');
// @doctest id="af44"
The preset selects the typesafe driver, https://api.typesafe.ai/v1/systemone, and the jev-latest model alias. Application Decision configuration lives under the sdm group:
# config/sdm/presets/typesafe.yaml
driver: typesafe
apiUrl: 'https://api.typesafe.ai/v1'
apiKey: '${TYPESAFE_API_KEY}'
endpoint: '/systemone'
model: 'jev-latest'
# @doctest id="dcd5"
DecisionConfig supports fromDefaults(), fromPreset(), presetNames(), fromArray(), fromDsn(), and immutable withOverrides(). Use toRedactedArray() rather than toArray() when configuration may reach logs or diagnostics.
use Cognesy\Polyglot\Decision\Config\DecisionConfig;
$config = DecisionConfig::fromPreset('typesafe')
->withOverrides(['model' => 'jev-latest']);
// @doctest id="7247"
A usable configuration requires non-empty driver, apiUrl, apiKey, endpoint, and model fields. The URL must be HTTP(S), and the endpoint must start with /.
Facade, provider, and runtime¶
Use the facade for ordinary calls:
$answers = Decision::fromConfig($config)
->with(input: $state, questions: $questions)
->get();
// @doctest id="8c23"
Use DecisionProvider when application composition needs reusable config overrides, a model override, or an explicit driver. Use DecisionRuntime when it needs an event root, HTTP client, driver registry, or retry-delay implementation.
use Cognesy\Polyglot\Decision\Decision;
use Cognesy\Polyglot\Decision\DecisionRuntime;
$runtime = DecisionRuntime::fromConfig(
config: $config,
events: $events,
httpClient: $httpClient,
);
$decision = Decision::fromRuntime($runtime);
// @doctest id="05c9"
The facade is immutable: withInput(), withQuestions(), withModel(), withRetryPolicy(), withRequest(), and the combined with() method return a copy.
Explicit requests¶
DecisionRequest is the provider-neutral execution input:
use Cognesy\Polyglot\Decision\Data\DecisionRequest;
$request = new DecisionRequest(
input: $state,
questions: $questions,
model: 'jev-latest',
);
$pending = $runtime->create($request);
// @doctest id="7490"
toArray() serializes only the portable payload: input, typed questions, and optional model. Request IDs, retry policy, and telemetry correlation are execution-envelope concerns and are intentionally not serialized. DecisionRequest::fromArray() restores the portable payload.
Retry policy¶
Decision performs one attempt unless a retry policy is supplied:
use Cognesy\Polyglot\Decision\Config\DecisionRetryPolicy;
$policy = new DecisionRetryPolicy(
maxAttempts: 3,
baseDelayMs: 250,
maxDelayMs: 4000,
jitter: 'full',
);
$pending = $decision->withRetryPolicy($policy)->create();
// @doctest id="4cdf"
The default retryable statuses are 408, 429, 500, 502, 503, 504, and 529, plus timeout and network failures. Bounded Retry-After is honored by default. The Decision execution session owns retries, so do not add HTTP retry middleware around the same operation.
Lifecycle events and telemetry¶
Register a specific listener or a wiretap on DecisionRuntime:
$runtime
->onEvent(DecisionCompleted::class, $onCompleted)
->wiretap($observeEveryDecisionEvent);
// @doctest id="54ae"
The event pairs are:
DecisionStartedfollowed byDecisionCompletedorDecisionFailedDecisionAttemptStartedfollowed byDecisionAttemptSucceededorDecisionAttemptFailed
Polyglot projects them as an sdm.decision span with sdm.decision.attempt children. Default event and telemetry attributes omit input state, instructions, criteria, provider bodies, credentials, and exception messages.
Custom drivers¶
A custom provider driver implements CanProcessDecisionRequest::handle(DecisionRequest): DecisionResponse. Register a class string or factory in DecisionDriverRegistry, then pass the registry to Decision::using(), Decision::fromConfig(), or DecisionRuntime::fromConfig():
use Cognesy\Polyglot\Decision\Creation\DecisionDriverRegistry;
$drivers = DecisionDriverRegistry::default()
->withDriver('acme', AcmeDecisionDriver::class);
$decision = Decision::fromConfig($config, drivers: $drivers);
// @doctest id="11c3"
Class-string drivers receive DecisionConfig, CanSendHttpRequests, and the event dispatcher. A factory receives the same three arguments. Provider adapters should translate between the stable DecisionRequest/DecisionResponse domain and the provider wire format; application code should not depend on the adapter classes.