STATEK Custom Providers
Custom providers let an application use STATEK with model APIs that are not built into the framework.
There are two supported paths:
- register a standard OpenAI-compatible chat-completions provider with
add_provider(...) - provide a custom
LLM_APIimplementation and register that class with STATEK
In both cases, registration happens in application or worker startup code before jobs start running.
Register an OpenAI-Compatible Provider
Use this path when the upstream API accepts an OpenAI-compatible chat-completions request.
from statek import add_provider
add_provider(
"SELLTIME",
api_url="https://selltime.ai/llm_api",
api_key="...",
)After registration, use the provider name in agent metadata:
# MODEL: model-1
# PROVIDER: SELLTIME
# System Prompt
You write Python against the objects available in context.add_provider(...) stores api_url and api_key as provider settings. The default implementation sends requests with the OpenAI-compatible payload shape described on Model Providers.
Environment-Based Settings
You can also register only the provider name and let STATEK read settings from the environment:
SELLTIME_API_URL=https://selltime.ai/llm_api
SELLTIME_API_KEY=XYZfrom statek import add_provider
add_provider("SELLTIME")Environment variable names start with the provider name. STATEK creates provider settings when both {PROVIDER}_API_URL and {PROVIDER}_API_KEY are present.
Optional provider fields use the same prefix:
SELLTIME_RESPONSE_FORMAT_FILE=./response-format.json
SELLTIME_USE_PROMPT_CACHING=falseDirect Provider Arguments
Provider-specific values can also be passed directly to add_provider(...):
from statek import add_provider
add_provider(
"CUSTOM_OPENAI",
api_url="https://models.example.com/v1/chat/completions",
api_key="...",
custom_payload="value",
timeout_hint=30,
)For the default OpenAI-compatible implementation, extra kwargs are included in the JSON request payload. Settings kwargs are not included in the payload:
api_urlapi_keyresponse_format_fileuse_prompt_caching
For custom implementations, kwargs are passed to the provider constructor. The implementation decides how to use them.
Do not pass secrets as extra payload kwargs unless the upstream provider explicitly expects them in the request body. Keep API keys in settings, environment variables, or a managed secret system.
add_provider(...)
The registration API is:
def add_provider(name: str, llm_api_impl: Type[LLM_API] = None, **kwargs):
...Arguments:
name: provider name. It is matched case-insensitively and must not collide with built-in provider names, built-in aliases, or an already registered custom provider.llm_api_impl: optional implementation class for theLLM_APIinterface. If omitted, STATEK uses the default OpenAI-compatible implementation.kwargs: optional settings and provider-specific constructor arguments.
Registration performs only the name uniqueness check. Bad credentials, missing settings, unsupported provider options, request-shape mismatches, and incomplete custom implementations surface when the provider is used.
When api_url and api_key are passed directly, STATEK creates LLM_API_Settings during registration. If either one is missing, provider settings are loaded later through the normal environment/settings flow.
If the same kwarg is supplied at registration and later through LLM_API.get(...), the later LLM_API.get(...) value wins for that provider instance.
Implement a Custom LLM_API
Use a custom implementation when the provider is not OpenAI-compatible or when you need custom authentication, payload formatting, response parsing, or usage accounting.
from statek import LLM_API, LLM_Response, LLM_Stats, add_provider
class CustomAPI(LLM_API):
def __init__(self, settings, **kwargs):
self.settings = settings
self.kwargs = kwargs
def _build_request_payload(
self,
system_prompt=None,
model=None,
metadata=None,
tools=None,
chat_history=None,
chat_style=None,
temperature=None,
enable_reasoning=False,
):
return {
"model": self.require_model(model),
"input": system_prompt or "",
}
async def _process_request(
self,
system_prompt=None,
model=None,
metadata=None,
tools=None,
chat_history=None,
chat_style=None,
temperature=None,
enable_reasoning=False,
):
payload = self._build_request_payload(
system_prompt=system_prompt,
model=model,
metadata=metadata,
tools=tools,
chat_history=chat_history,
chat_style=chat_style,
temperature=temperature,
enable_reasoning=enable_reasoning,
)
# Send payload to your provider and parse the response here.
# This example returns a fixed response to show the required shape.
return LLM_Response(
text="print('hello from custom provider')",
stats=LLM_Stats(
total_bytes_sent=0,
total_bytes_received=0,
cost=0,
input_tokens=0,
output_tokens=0,
cached_tokens=0,
),
call_requests=None,
)
add_provider(
"CUSTOM",
llm_api_impl=CustomAPI,
api_url="https://models.example.com/custom",
api_key="...",
vendor_option="value",
)LLM_API.process_request(...) handles shared validation and tool-scope selection, then calls your _process_request(...). Your implementation should:
- build the provider-specific request payload
- send the HTTP request or call the provider SDK
- parse text responses into
LLM_Response.text - parse tool calls into
LLM_Response.call_requestswhen the provider supports tools - return
LLM_Statswith usage data when available
Operational Notes
Register custom providers during process startup before creating or running jobs. Provider registration is in memory for the current Python process.
The provider factory and settings helpers are cached for long-running workers. In tests or dynamic configuration scenarios, clear the relevant caches before expecting changed environment variables or registrations to be visible.
Provider setup does not sandbox agent-executed Python. Keep sandboxing, permissioning, secrets discipline, resource limits, logging, and provider quota controls in your application and deployment layer.
Where to go next
Read Model Providers for built-in provider setup, Configuration for settings precedence, Security for credentials and runtime boundaries, and API Reference for add_provider(...) and LLM_API.