praval.models
Provider-neutral model contracts for Praval.
These types describe model input, output, tools, events, and capabilities without binding the rest of Praval to one provider’s wire format.
Classes
|
Provider-neutral transcription or synthesized-audio response. |
|
A single multimodal content part. |
|
Provider-neutral embedding request. |
|
Provider-neutral embedding response. |
|
A streaming model event. |
|
A provider-neutral conversation message. |
|
Provider-neutral model request. |
|
Provider-neutral model response. |
|
Protocol implemented by provider-neutral adapters. |
|
Capabilities exposed by a provider or a provider/model pair. |
|
A registered provider/model profile. |
|
Reasoning controls for providers that support them. |
|
Provider-neutral request to synthesize speech from text. |
|
Structured output request configuration. |
|
A model-requested tool invocation. |
|
A result returned from a tool invocation. |
|
Provider-neutral tool declaration. |
|
Provider-neutral request to transcribe an audio file or byte payload. |
|
Provider-neutral token usage. |
- class praval.models.AudioResponse(**data)[source]
Bases:
BaseModelProvider-neutral transcription or synthesized-audio response.
- Parameters:
text (str | None)
data (bytes | None)
provider (str | None)
model (str | None)
format (str | None)
mime_type (str | None)
raw (Any)
metadata (Dict[str, Any])
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- text: str | None
- data: bytes | None
- provider: str | None
- model: str | None
- format: str | None
- mime_type: str | None
- raw: Any
- metadata: Dict[str, Any]
- class praval.models.ContentKind(*values)[source]
Bases:
str,EnumSensitive content category represented by a safe reference.
- PROMPT = 'prompt'
- RESPONSE = 'response'
- CONTEXT = 'context'
- TOOL_ARGUMENTS = 'tool_arguments'
- TOOL_RESULT = 'tool_result'
- RETRIEVED_DOCUMENT = 'retrieved_document'
- MEDIA = 'media'
- JUDGE_EVIDENCE = 'judge_evidence'
- OTHER = 'other'
- class praval.models.ContentPart(**data)[source]
Bases:
BaseModelA single multimodal content part.
- Parameters:
type (str)
text (str | None)
data (str | None)
url (str | None)
mime_type (str | None)
metadata (Dict[str, Any])
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- type: str
- text: str | None
- data: str | None
- url: str | None
- mime_type: str | None
- metadata: Dict[str, Any]
- classmethod text_part(text)[source]
Create a text content part.
- Return type:
- Parameters:
text (str)
- classmethod image_url(url, mime_type=None)[source]
Create an image URL content part.
- Return type:
- Parameters:
url (str)
mime_type (str | None)
- classmethod image_base64(data, mime_type='image/png')[source]
Create an inline base64 image content part.
- Return type:
- Parameters:
data (str)
mime_type (str)
- classmethod audio_url(url, mime_type=None)[source]
Create an audio URL content part.
- Return type:
- Parameters:
url (str)
mime_type (str | None)
- classmethod audio_base64(data, mime_type='audio/wav')[source]
Create an inline base64 audio content part.
- Return type:
- Parameters:
data (str)
mime_type (str)
- classmethod video_url(url, mime_type=None)[source]
Create a video URL content part.
- Return type:
- Parameters:
url (str)
mime_type (str | None)
- classmethod video_base64(data, mime_type='video/mp4')[source]
Create an inline base64 video content part.
- Return type:
- Parameters:
data (str)
mime_type (str)
- classmethod file_url(url, mime_type='application/octet-stream', *, name=None)[source]
Create a remote file content part.
- Return type:
- Parameters:
url (str)
mime_type (str)
name (str | None)
- class praval.models.ContentReference(**data)[source]
Bases:
_ObservationModelSafe identity for content that is not embedded in an observation.
- Parameters:
kind (ContentKind)
sha256 (str)
size_bytes (int)
reference (str | None)
media_type (str | None)
- kind: ContentKind
- sha256: str
- size_bytes: int
- reference: str | None
- media_type: str | None
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.EmbeddingRequest(**data)[source]
Bases:
BaseModelProvider-neutral embedding request.
- Parameters:
inputs (List[Any])
provider (str | None)
model (str | None)
dimensions (int | None)
provider_options (Dict[str, Any])
metadata (Dict[str, Any])
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- inputs: List[Any]
- provider: str | None
- model: str | None
- dimensions: int | None
- provider_options: Dict[str, Any]
- metadata: Dict[str, Any]
- class praval.models.EmbeddingResponse(**data)[source]
Bases:
BaseModelProvider-neutral embedding response.
- Parameters:
embeddings (List[List[float]])
provider (str | None)
model (str | None)
dimensions (int | None)
raw (Any)
metadata (Dict[str, Any])
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- embeddings: List[List[float]]
- provider: str | None
- model: str | None
- dimensions: int | None
- raw: Any
- metadata: Dict[str, Any]
- class praval.models.ExecutionObservation(**data)[source]
Bases:
_ObservationModelVersioned facts for one completed agent invocation or workflow.
The schema contains identities and bounded metadata only. Raw prompts, responses, tool payloads, retrieved documents, media, and judge evidence are represented through
ContentReferencevalues.- Parameters:
schema_version (Literal[1])
observation_id (str)
run_id (str)
kind (ObservationKind)
conversation_id (str | None)
response_id (str | None)
agent_id (str | None)
agent_name (str | None)
workflow_id (str | None)
workflow_name (str | None)
started_at (datetime)
ended_at (datetime)
duration_ms (float)
status (ObservationStatus)
error_type (str | None)
terminal_outcome (str | None)
provider (str | None)
model (str | None)
request_mode (str | None)
usage (TokenUsageObservation | None)
tool_calls (tuple[ToolCallObservation, ...])
retries (tuple[RetryObservation, ...])
hitl_decisions (tuple[HITLDecisionObservation, ...])
handoffs (tuple[ReefHandoffObservation, ...])
content_references (tuple[ContentReference, ...])
privacy (ObservationPrivacy)
trace_id (str | None)
span_id (str | None)
- schema_version: Literal[1]
- observation_id: str
- run_id: str
- kind: ObservationKind
- conversation_id: str | None
- response_id: str | None
- agent_id: str | None
- agent_name: str | None
- workflow_id: str | None
- workflow_name: str | None
- started_at: datetime
- ended_at: datetime
- duration_ms: float
- status: ObservationStatus
- error_type: str | None
- terminal_outcome: str | None
- provider: str | None
- model: str | None
- request_mode: str | None
- usage: TokenUsageObservation | None
- tool_calls: tuple[ToolCallObservation, ...]
- retries: tuple[RetryObservation, ...]
- hitl_decisions: tuple[HITLDecisionObservation, ...]
- handoffs: tuple[ReefHandoffObservation, ...]
- content_references: tuple[ContentReference, ...]
- privacy: ObservationPrivacy
- trace_id: str | None
- span_id: str | None
- classmethod require_utc(value)[source]
Require timezone-aware timestamps and normalize them to UTC.
- Return type:
datetime- Parameters:
value (datetime)
- validate_contract()[source]
Validate cross-field identity, timing, error, and trace invariants.
- Return type:
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.HITLDecisionObservation(**data)[source]
Bases:
_ObservationModelMetadata-only human-in-the-loop decision.
- Parameters:
decision_id (str)
decision (Literal['requested', 'approved', 'rejected', 'edited', 'timeout', 'cancelled'])
tool_name (str | None)
reviewer_type (str | None)
- decision_id: str
- decision: Literal['requested', 'approved', 'rejected', 'edited', 'timeout', 'cancelled']
- tool_name: str | None
- reviewer_type: str | None
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.ModelEvent(**data)[source]
Bases:
BaseModelA streaming model event.
- Parameters:
type (str)
delta (str)
response (ModelResponse | None)
tool_call (ToolCall | None)
tool_result (ToolResult | None)
usage (Usage | None)
metadata (Dict[str, Any])
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- type: str
- delta: str
- response: ModelResponse | None
- tool_result: ToolResult | None
- metadata: Dict[str, Any]
- class praval.models.ModelMessage(**data)[source]
Bases:
BaseModelA provider-neutral conversation message.
- Parameters:
role (str)
content (Any)
name (str | None)
tool_call_id (str | None)
metadata (Dict[str, Any])
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- role: str
- content: Any
- name: str | None
- tool_call_id: str | None
- metadata: Dict[str, Any]
- class praval.models.ModelRequest(**data)[source]
Bases:
BaseModelProvider-neutral model request.
- Parameters:
messages (List[ModelMessage])
provider (str | None)
model (str | None)
tools (List[ToolSpec])
temperature (float | None)
max_output_tokens (int | None)
max_tool_rounds (int | None)
stream (bool)
response_schema (StructuredOutputConfig | None)
reasoning (ReasoningConfig | None)
provider_options (Dict[str, Any])
stream_options (Dict[str, Any])
timeout (float | None)
metadata (Dict[str, Any])
hitl_context (Dict[str, Any] | None)
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- messages: List[ModelMessage]
- provider: str | None
- model: str | None
- temperature: float | None
- max_output_tokens: int | None
- max_tool_rounds: int | None
- stream: bool
- response_schema: StructuredOutputConfig | None
- reasoning: ReasoningConfig | None
- provider_options: Dict[str, Any]
- stream_options: Dict[str, Any]
- timeout: float | None
- metadata: Dict[str, Any]
- hitl_context: Dict[str, Any] | None
- class praval.models.ModelResponse(**data)[source]
Bases:
BaseModelProvider-neutral model response.
- Parameters:
content (str)
provider (str | None)
model (str | None)
messages (List[ModelMessage])
tool_calls (List[ToolCall])
usage (Usage | None)
finish_reason (str | None)
raw (Any)
metadata (Dict[str, Any])
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- content: str
- provider: str | None
- model: str | None
- messages: List[ModelMessage]
- finish_reason: str | None
- raw: Any
- metadata: Dict[str, Any]
- property text: str
Return response content as text.
- class praval.models.NoOpObservationRecorder[source]
Bases:
objectDefault recorder used when no observation consumer is configured.
- record(observation)[source]
Discard an observation without side effects.
- Return type:
None- Parameters:
observation (ExecutionObservation)
- class praval.models.ObservationFactStatus(*values)[source]
Bases:
str,EnumStatus shared by bounded child facts such as tools and handoffs.
- OK = 'ok'
- ERROR = 'error'
- CANCELLED = 'cancelled'
- TIMEOUT = 'timeout'
- REJECTED = 'rejected'
- class praval.models.ObservationKind(*values)[source]
Bases:
str,EnumExecution boundary represented by an observation.
- AGENT = 'agent'
- WORKFLOW = 'workflow'
- class praval.models.ObservationPrivacy(**data)[source]
Bases:
_ObservationModelPrivacy policy applied to all content facts in an observation.
- Parameters:
mode (PrivacyMode)
content_captured (bool)
redaction_applied (bool)
byte_limit (int)
- mode: PrivacyMode
- content_captured: bool
- redaction_applied: bool
- byte_limit: int
- validate_capture_policy()[source]
Keep metadata-only observations free from captured content.
- Return type:
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.ObservationRecorder(*args, **kwargs)[source]
Bases:
ProtocolStructural interface for consumers of completed observations.
- record(observation)[source]
Record one completed execution observation.
- Return type:
None- Parameters:
observation (ExecutionObservation)
- __init__(*args, **kwargs)
- class praval.models.ObservationStatus(*values)[source]
Bases:
str,EnumTerminal status of an observed execution.
- OK = 'ok'
- ERROR = 'error'
- CANCELLED = 'cancelled'
- TIMEOUT = 'timeout'
- class praval.models.PrivacyMode(*values)[source]
Bases:
str,EnumContent handling policy applied before an observation is recorded.
- METADATA_ONLY = 'metadata_only'
- REDACTED = 'redacted'
- FULL = 'full'
- class praval.models.ProviderAdapter(*args, **kwargs)[source]
Bases:
ProtocolProtocol implemented by provider-neutral adapters.
- provider_name: str
- capabilities: ProviderCapabilities
- invoke(request)[source]
Execute a non-streaming model request.
- Return type:
- Parameters:
request (ModelRequest)
- stream(request)[source]
Execute a streaming model request.
- Return type:
Iterator[ModelEvent]- Parameters:
request (ModelRequest)
- async ainvoke(request)[source]
Execute a non-streaming request asynchronously.
- Return type:
- Parameters:
request (ModelRequest)
- astream(request)[source]
Execute a streaming model request asynchronously.
- Return type:
AsyncIterator[ModelEvent]- Parameters:
request (ModelRequest)
- __init__(*args, **kwargs)
- class praval.models.ProviderCapabilities(**data)[source]
Bases:
BaseModelCapabilities exposed by a provider or a provider/model pair.
- Parameters:
text (bool)
chat_completions (bool)
responses_api (bool)
tools (bool)
streaming (bool)
native_streaming (bool)
tool_streaming (bool)
structured_outputs (bool)
json_schema_mode (str | None)
multimodal (bool)
image_input (bool)
file_input (bool)
audio_input (bool)
video_input (bool)
audio_transcription (bool)
speech_generation (bool)
reasoning (bool)
reasoning_effort (bool)
reasoning_budget (bool)
embeddings (bool)
local (bool)
server_tools (bool)
mcp (bool)
computer_use (bool)
- text: bool
- chat_completions: bool
- responses_api: bool
- tools: bool
- streaming: bool
- native_streaming: bool
- tool_streaming: bool
- structured_outputs: bool
- json_schema_mode: str | None
- multimodal: bool
- image_input: bool
- file_input: bool
- audio_input: bool
- video_input: bool
- audio_transcription: bool
- speech_generation: bool
- reasoning: bool
- reasoning_effort: bool
- reasoning_budget: bool
- embeddings: bool
- local: bool
- server_tools: bool
- mcp: bool
- computer_use: bool
- supports(capability)[source]
Return whether a named capability is enabled.
- Return type:
bool- Parameters:
capability (str)
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.ProviderProfile(**data)[source]
Bases:
BaseModelA registered provider/model profile.
- Parameters:
provider (str)
model (str)
display_name (str | None)
capabilities (ProviderCapabilities)
default (bool)
endpoint (str | None)
local_preset (str | None)
context_window (int | None)
max_output_tokens (int | None)
default_parameters (Dict[str, Any])
unsupported_combinations (List[Dict[str, Any]])
downgrade_policy (str)
notes (str)
- provider: str
- model: str
- display_name: str | None
- capabilities: ProviderCapabilities
- default: bool
- endpoint: str | None
- local_preset: str | None
- context_window: int | None
- max_output_tokens: int | None
- default_parameters: Dict[str, Any]
- unsupported_combinations: List[Dict[str, Any]]
- downgrade_policy: str
- notes: str
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.ReasoningConfig(**data)[source]
Bases:
BaseModelReasoning controls for providers that support them.
- Parameters:
effort (str | None)
summary (str | None)
encrypted (bool)
budget_tokens (int | None)
mode (str | None)
display (str | None)
- effort: str | None
- summary: str | None
- encrypted: bool
- budget_tokens: int | None
- mode: str | None
- display: str | None
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.ReefHandoffObservation(**data)[source]
Bases:
_ObservationModelMetadata-only facts about one Reef handoff.
- Parameters:
handoff_id (str)
source_agent_id (str | None)
target_agent_id (str)
spore_id (str | None)
channel (str | None)
status (ObservationFactStatus)
duration_ms (float | None)
error_type (str | None)
- handoff_id: str
- source_agent_id: str | None
- target_agent_id: str
- spore_id: str | None
- channel: str | None
- status: ObservationFactStatus
- duration_ms: float | None
- error_type: str | None
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.RetryObservation(**data)[source]
Bases:
_ObservationModelOne bounded retry decision made during execution.
- Parameters:
attempt (int)
operation (str)
reason_type (str | None)
backoff_ms (float)
- attempt: int
- operation: str
- reason_type: str | None
- backoff_ms: float
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.SpeechRequest(**data)[source]
Bases:
BaseModelProvider-neutral request to synthesize speech from text.
- Parameters:
input (str)
provider (str | None)
model (str | None)
voice (str)
response_format (str)
speed (float)
instructions (str | None)
provider_options (Dict[str, Any])
timeout (float | None)
metadata (Dict[str, Any])
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- input: str
- provider: str | None
- model: str | None
- voice: str
- response_format: str
- speed: float
- instructions: str | None
- provider_options: Dict[str, Any]
- timeout: float | None
- metadata: Dict[str, Any]
- class praval.models.StructuredOutputConfig(**data)[source]
Bases:
BaseModelStructured output request configuration.
- Parameters:
schema (Dict[str, Any] | None)
name (str | None)
strict (bool)
- model_config: ClassVar[ConfigDict] = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- json_schema: Dict[str, Any] | None
- name: str | None
- strict: bool
- class praval.models.ToolCall(**data)[source]
Bases:
BaseModelA model-requested tool invocation.
- Parameters:
id (str)
name (str)
arguments (Dict[str, Any])
raw (Any)
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- id: str
- name: str
- arguments: Dict[str, Any]
- raw: Any
- class praval.models.ToolResult(**data)[source]
Bases:
BaseModelA result returned from a tool invocation.
- Parameters:
tool_call_id (str)
name (str)
content (str)
is_error (bool)
metadata (Dict[str, Any])
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- tool_call_id: str
- name: str
- content: str
- is_error: bool
- metadata: Dict[str, Any]
- class praval.models.ToolSpec(**data)[source]
Bases:
BaseModelProvider-neutral tool declaration.
- Parameters:
name (str)
description (str)
parameters (Dict[str, Any])
strict (bool)
requires_approval (bool)
risk_level (str)
approval_reason (str)
metadata (Dict[str, Any])
extra_data (Any)
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- name: str
- description: str
- parameters: Dict[str, Any]
- strict: bool
- requires_approval: bool
- risk_level: str
- approval_reason: str
- metadata: Dict[str, Any]
- class praval.models.TranscriptionRequest(**data)[source]
Bases:
BaseModelProvider-neutral request to transcribe an audio file or byte payload.
- Parameters:
audio (Any)
provider (str | None)
model (str | None)
filename (str | None)
mime_type (str | None)
language (str | None)
prompt (str | None)
response_format (str)
temperature (float | None)
provider_options (Dict[str, Any])
timeout (float | None)
metadata (Dict[str, Any])
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- audio: Any
- provider: str | None
- model: str | None
- filename: str | None
- mime_type: str | None
- language: str | None
- prompt: str | None
- response_format: str
- temperature: float | None
- provider_options: Dict[str, Any]
- timeout: float | None
- metadata: Dict[str, Any]
- class praval.models.TokenUsageObservation(**data)[source]
Bases:
_ObservationModelBounded provider-neutral model token usage.
- Parameters:
input_tokens (int)
output_tokens (int)
reasoning_tokens (int)
cache_read_tokens (int)
cache_write_tokens (int)
total_tokens (int)
- input_tokens: int
- output_tokens: int
- reasoning_tokens: int
- cache_read_tokens: int
- cache_write_tokens: int
- total_tokens: int
- validate_total()[source]
Reject totals smaller than the directly billed token classes.
- Return type:
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.Usage(**data)[source]
Bases:
BaseModelProvider-neutral token usage.
- Parameters:
input_tokens (int)
output_tokens (int)
total_tokens (int)
reasoning_tokens (int)
- input_tokens: int
- output_tokens: int
- total_tokens: int
- reasoning_tokens: int
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class praval.models.ToolCallObservation(**data)[source]
Bases:
_ObservationModelMetadata-only facts about one tool invocation.
- Parameters:
tool_call_id (str)
name (str)
status (ObservationFactStatus)
duration_ms (float)
error_type (str | None)
- tool_call_id: str
- name: str
- status: ObservationFactStatus
- duration_ms: float
- error_type: str | None
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].