Skip to content

Documentation navigation

Data Models

The typed shapes you read off responses and pass in - SessionResponse, RawSSEEvent, TokenUsage, the privacy models, and billing/usage models.

#Shared Data Models

The typed Pydantic shapes you construct as agent input (messages, private-data descriptors) and read back as agent output (response objects, event streams, token counts), shared across the mAIvn libraries.

These are the structural counterpart to the maivn SDK docs: that reference describes behavior (how to build, invoke, and stream an agent), while this page describes the shapes that behavior produces and consumes.

Note Most of these models are importable from maivn, maivn.messages, or maivn.events, as shown in each section. Token usage is exposed as a dictionary on InvokeResponse, not as a public model.

#InvokeResponse and StreamEvent

These are the two shapes an invocation hands back.

#InvokeResponse

Agent.invoke(), Agent.ainvoke(), Swarm.invoke(), and Swarm.ainvoke() all return a single InvokeResponse. It is the canonical "what happened in this turn" object.

Python
from maivn import Agent
from maivn.messages import HumanMessage

agent = Agent(name='assistant', api_key='...')
response = agent.invoke([HumanMessage(content='Summarize this ticket.')])

print(response.response)   # final assistant text
print(response.result)     # structured / final-tool output, when applicable
print(response.stop_reason)
FieldTypeWhat it holds
final_messageMessageCanonical final message contract.
responsestrConvenience text copied from final_message.content when that content is text.
responseslist[str]Compatibility list containing response when non-empty.
resultobject | NoneStructured or final-tool output.
session_idstrSession identifier.
thread_idstr | NoneConversation thread identifier.
root_event_idstrRoot event identifier for the invocation.
event_positionslist[int]Stream positions consumed to produce the result.
usagedict[str, object]Raw usage metadata.
token_usagedict[str, int] | NoneNormalized token counters when input/output counts are present.
stop_reasonstr | NoneProvider/runtime stop reason.
tool_call_count / tool_namesint / list[str]Tool execution summary.
assistant_idstr | NoneAssistant identifier when supplied.
artifactstuple[ArtifactRef, ...]Verified references to generated files selected for this response.
provider_usageProviderUsage | NoneProvider-reported usage when supplied; see Usage and Cost.
privacy_guidancelist[dict[str, object]]Advisory over-redaction feedback, empty when absent. May contain actual delivered values; trusted developer display only, never log/persist. See Private Data.
response vs. result response is the human-readable answer. result is machine-readable output, populated when you force a final tool or request structured output. A typical text turn fills response and leaves result as None; a structured-output turn fills both.
Python
from pydantic import BaseModel

class Summary(BaseModel):
    title: str
    bullets: list[str]

response = agent.structured_output(Summary).invoke(
    [HumanMessage(content='Summarize this ticket.')]
)

summary = response.result   # a typed Summary instance
print(summary.title, summary.bullets)

#StreamEvent

Agent.stream() and Swarm.stream() yield maivn.StreamEvent. It retains the canonical event envelope (position, event_type, and data) and exposes compatibility name and payload properties for common event handling.

Python
from maivn import StreamEvent

event = StreamEvent(position=0, event_type="run.started", data={})
print(event.position, event.event_type, event.data)

You can read it directly when you just need the raw stream:

Python
for event in agent.stream([HumanMessage(content='Think through this.')]):
    if event.name == 'system_tool_chunk':
        print(event.payload.get('text', ''), end='')
    elif event.name == 'final':
        print('\nDone')
Tip For product integrations, adapt each StreamEvent to RawSSEEvent(name=event.name, payload=event.payload) and normalize once with maivn.events.normalize_stream(...). The result is a descriptor-rich AppEvent stream.

#Token usage

InvokeResponse.token_usage is a normalized dictionary derived from response.usage. It is None when neither input nor output counts are present.

Python
usage = response.token_usage
if usage is not None:
    print(usage['total_tokens'], 'total')
    print(usage['input_tokens'], 'in /', usage['output_tokens'], 'out')
FieldTypeMeaning
total_tokensintTotal tokens used (input + output).
input_tokensintInput / prompt tokens.
output_tokensintOutput / completion tokens.
cache_read_tokensintTokens served from the provider's prompt cache.
cache_creation_tokensintTokens written to the provider's prompt cache.
reasoning_tokensintReasoning / extended-thinking tokens, where the model reports them.

All values in the normalized dictionary are integers. total_tokens is currently input_tokens + output_tokens; cache and reasoning counters remain separately available.

No cost by design Per-run usage carries token counts only. The billing models below validate aggregated data obtained through an authorized application integration; the public Client does not fetch it.

#Public Billing / Usage Models

These models describe an organization's plan and usage for a billing period. Every model is importable from maivn and ignores unknown fields, so it can validate extensible payloads obtained outside the current public client surface.

BillingUsage represents a single account-level usage snapshot:

FieldTypeDescription
organization_idstrThe organization the key belongs to.
period_startstrISO-8601 start of the billing period (inclusive).
period_endstrISO-8601 period end supplied by the billing integration.
planBillingPlan | NoneCurrent plan summary, or None if no active plan.
usageBillingCurrentUsageUsage counters and their limits.
breakdownBillingUsageBreakdownUsage grouped org → project → API key.

The nested shapes:

  • BillingPlan — name, display_name, tier.
  • BillingCurrentUsage — tokens_used, tokens_used_raw, tokens_limit, requests_used, requests_limit, storage_used, storage_limit. A limit of -1 means unlimited.
  • BillingUsageBreakdown — organization_id, period_start, period_end, totals (a BillingUsageTotals), and projects (a list of BillingUsageProject).
  • BillingUsageTotals — billed_tokens, raw_tokens, requests.
  • BillingUsageProject — project_id (None for the unattributed bucket), project_name, billed_tokens, raw_tokens, requests, and api_keys (a list of BillingUsageApiKey).
  • BillingUsageApiKey — api_key_id (None for the "Unknown API key" bucket), api_key_name, billed_tokens, raw_tokens, requests.
Python
from maivn import BillingUsage

usage = BillingUsage.model_validate(usage_payload)
print(usage.plan.tier if usage.plan else 'no plan')
print(f'{usage.usage.tokens_used:,} / {usage.usage.tokens_limit:,} tokens')

The current public Client has no get_usage() transport method. See the billing-model reference for the supported read-model boundary.

#Privacy Models

These shapes let you declare sensitive data so it is handled safely rather than passed to the model in cleartext. The conceptual model is: the LLM plans against a schema (field names, types, and labels), and real values are injected into tools only at execution time. The companion behavior (how to attach private_data to an agent and inject values into tools) lives in the Private Data guide. This section covers the shapes you construct.

Controls, not certifications. These are technical privacy controls, not certifications. mAIvn holds no SOC 2, HIPAA, ISO 27001, or FedRAMP certification. phi_mode limits HIPAA Safe Harbor whitelist categories; it does not make a deployment HIPAA-compliant, provide a BAA, or replace required audits and organizational controls. Evaluate and use these controls at your own risk under the mAIvn Platform Disclaimer.

Import them from the SDK:

Python
from maivn.messages import RedactedMessage, PrivateData
from maivn import PIIWhitelist, PIIWhitelistEntry, HIPAA_SAFE_HARBOR_CATEGORIES

#PrivateData

A structured descriptor for a known sensitive value. It enriches the schema the model sees with a custom key name, type, and label, without ever exposing the value itself to the model by default.

Plain text
PrivateData(
    value: object,                  # the actual sensitive value (required)
    name: str | None = None,        # custom placeholder key, e.g. 'patient_name'
    pii_type: str | None = None,    # entity type: 'person', 'phone', 'email', 'date', ...
    label: str | None = None,       # human-readable label shown in the schema
    description: str | None = None, # extra context for the model
    format: str | None = None,      # semantic format hint: 'email', 'phone', 'date', ...
)

In RedactedMessage.known_pii_values, descriptors retain their metadata and declared names receive user_ placeholder keys. A scope's private_data list normalizes descriptors to their names and values only; it discards labels, entity types, descriptions, and format hints. Use a redacted message when that metadata needs to reach the runtime.

Python
agent = Agent(
    name='intake',
    api_key='...',
    private_data=[
        PrivateData(value='Maria Santos', name='patient_name', pii_type='person',
                    label='Patient Name'),
        PrivateData(value='MEM-882441', name='member_id', label='Member ID'),
    ],
)

#RedactedMessage

A message type that triggers automatic PII detection on the user-supplied text. Send one instead of a HumanMessage when the input may contain sensitive values you want detected and redacted before any model-visible context is built.

Plain text
RedactedMessage(
    content: str | list[ContentBlock],
    known_pii_values: list[str | PrivateData] | None = None,
    pii_whitelist: PIIWhitelist | None = None,
    attachments: list[Attachment] | None = None,
    metadata: dict[str, MetadataValue] | None = None,
    message_id: str = ...,
    ts: str = ...,
)
Python
from maivn.messages import RedactedMessage

response = agent.invoke([
    RedactedMessage(content='My email is john@example.com and SSN is 123-45-6789.')
])

Use known_pii_values to declare values explicitly (raw strings or PrivateData descriptors) so they are scrubbed even if auto-detection does not catch them. The runtime detects common identifier categories (email, phone, SSN, credit card, IBAN/SWIFT, medical record numbers, VINs, and named entities such as person, location, date, IP, and URL), each paired with a structural validator to avoid flagging look-alikes like order numbers.

#PIIWhitelist and PIIWhitelistEntry

Configuration for leaving approved spans in cleartext. The whitelist is evaluated after detection (so the value is still recorded as having been present) but before the value would be registered as private, so the matched span passes through.

Plain text
PIIWhitelist(
    entries: tuple[PIIWhitelistEntry, ...] = (),
    phi_mode: bool = False,
)

PIIWhitelistEntry(
    entity_type: str | None = None,   # one-of: a whole category
    pattern: str | None = None,       # one-of: a regex
    value: str | None = None,         # one-of: a literal value
    justification: str = ...,         # required, >= 8 characters
    label: str | None = None,
)

Each entry matches by one of entity_type, pattern, or value, and every entry requires a justification of at least 8 characters. Setting phi_mode=True refuses entity_type entries for any HIPAA Safe Harbor category at construction (raising ValueError). Use a specific value or pattern for individually approved instances instead. Both models are frozen (immutable after construction).

Python
whitelist = PIIWhitelist(
    entries=(
        PIIWhitelistEntry(
            entity_type='url',
            justification='Public marketing URLs needed for citations.',
        ),
        PIIWhitelistEntry(
            value='support@maivn.io',
            justification='Public support address listed on the docs site.',
        ),
    ),
)

message = RedactedMessage(
    content='See https://maivn.io and email support@maivn.io',
    pii_whitelist=whitelist,
)

#HIPAA_SAFE_HARBOR_CATEGORIES

An exported constant: a frozenset of the canonical entity-type names that phi_mode=True blocks from entity_type whitelisting. Use it to validate your own policy before constructing a PIIWhitelist.

Python
from maivn import HIPAA_SAFE_HARBOR_CATEGORIES

if 'person' in HIPAA_SAFE_HARBOR_CATEGORIES:
    # ... avoid a category-wide whitelist for names under phi_mode
    ...

#Message Types

Messages are how you talk to an agent and how it talks back. They live in maivn.messages and are the input shapes for every invoke() / stream() call.

Python
from maivn.messages import HumanMessage, AIMessage, SystemMessage
TypeDirectionWhat it is
HumanMessageinputUser input to the agent. Supports content plus optional attachments.
AIMessageoutputAn assistant response. Usually read off a result, rarely constructed by hand.
SystemMessageinputA system prompt that sets agent behavior. Often passed as the constructor's system_prompt.
Python
from maivn.messages import SystemMessage, HumanMessage

messages = [
    SystemMessage(content='You are a concise Python expert.'),
    HumanMessage(content='How do I read a file?'),
]
response = agent.invoke(messages)

If you set system_prompt on the Agent constructor and your messages do not include a SystemMessage, one is injected automatically. RedactedMessage (above) is the privacy-aware sibling of HumanMessage. For the full message surface (attachments, multi-turn patterns, and BaseMessage for type hints), see the Messages reference.

#See Also

  • SDK Reference — the behavioral surface: Agent, Swarm, tools, events, scheduling.
  • Messages reference — full message and privacy-model details, attachments, and patterns.
  • Private Data guide — how the schema-only planning and runtime-injection model works end to end.
  • Billing models — supported read models and the deliberately absent client transport.
  • Events reference — normalizing the raw stream into the AppEvent contract for frontends.