Model Runtime

ModelRuntime is the execution boundary between agents and provider adapters. It owns provider-neutral request validation, capability resolution, retry policy, tracing spans, legacy tool execution hooks, HITL resume metadata, and the normalized response/event types in praval.models.

Prefer this path for new code:

from praval import Agent

agent = Agent("planner", provider="openai", model="gpt-5.4-mini")
response = agent.generate(
    "Return a JSON task list.",
    response_schema={
        "type": "object",
        "properties": {"tasks": {"type": "array", "items": {"type": "string"}}},
        "required": ["tasks"],
    },
    metadata={"workflow": "planning"},
)

print(response.content)

Agent.chat() remains compatible and returns only a string. Agent.generate(), Agent.agenerate(), Agent.stream(), and Agent.astream() return or emit structured runtime types.

Request Options

The same options are accepted by sync, async, and streaming calls:

Option

Purpose

response_schema

Provider-neutral structured output schema.

reasoning

Reasoning effort, display mode, or budget settings.

provider_options

Provider-specific options after runtime safety checks.

timeout

Per-call timeout when the adapter supports it.

metadata

User metadata for tracing and diagnostics.

stream_options

Streaming options such as usage inclusion.

Unsafe provider options such as API keys, raw authorization headers, and custom default headers are rejected before provider execution.

Public Inspection

Use the registry and runtime to inspect behavior before executing a call:

from praval import Agent, ModelMessage, ModelRequest

agent = Agent("local", provider="ollama", model="llama3")
request = ModelRequest(
    provider="ollama",
    model="llama3",
    messages=[ModelMessage(role="user", content="hello")],
)

capabilities = agent.runtime.resolve_capabilities(request)
agent.runtime.validate_request(request)

For production code that needs preflight checks, construct praval.models.ModelRequest directly and pass it to resolve_capabilities() or validate_request().

Runtime Events

Streaming emits normalized ModelEvent values:

Event

Meaning

start

Runtime accepted the request and resolved stream capability.

delta

Text delta.

tool_call_delta

Partial tool-call arguments or provider tool-call delta.

tool_call

Complete tool call request.

tool_result

Tool result emitted by runtime-owned orchestration.

usage

Token usage update.

error

Provider or stream error, with redacted metadata.

final

Final ModelResponse.

Adapters may expose more provider metadata, but user code should branch on the normalized event type first.

Client Tool Orchestration

Client/function tools are runtime-owned in 0.8. A provider adapter only translates declarations, tool calls, and tool results. For each response, ModelRuntime executes all requested client tools, records ordered ToolCall/ToolResult values, asks the provider to continue, and repeats up to the configured tool-round limit. Sync tools, async tools, sync streaming, and async streaming share this orchestration path.

Tools marked requires_approval=True are evaluated by the HITL runtime before execution. An intervention stores JSON-safe provider-neutral continuation state. After the operator approves, edits, or rejects the call, Agent.resume_run(run_id) reconstructs the request and response, completes the remaining tool calls, and continues the model loop. Legacy provider-specific continuation schemas remain readable for compatibility.

Provider-hosted tools are a separate experimental pass-through. See Providers for the explicit opt-in and security restrictions.