Private Data
Pass private values to tools, restore placeholders, and use RedactedMessage.
Privacy control, not certification
mAIvn holds no SOC 2, HIPAA, ISO 27001, or FedRAMP certification. Use these controls at your own risk under the Platform Disclaimer.
#Private Data
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, guarantee detection, or replace required audits and organizational controls. Evaluate and use these controls at your own risk under the mAIvn Platform Disclaimer.Examples of private-data injection and runtime redaction. Replace the example credentials before running them. Injection keeps declared values out of model arguments; automatic PII detection is an additional, fallible control.
#@depends_on_private_data — inject without disclosure
The injected argument is hidden from the model-facing argument schema. The runtime supplies its value just before calling the tool:
from maivn import Agent, depends_on_private_data
from maivn.messages import HumanMessage
agent = Agent(name='Account Briefing Agent', system_prompt='...', api_key='...')
@depends_on_private_data(arg_name='account_id', data_key='account_id')
@depends_on_private_data(arg_name='customer_name', data_key='customer_name')
@agent.toolify(name='account_briefing', final_tool=True)
def account_briefing(account_id: str, customer_name: str) -> dict:
return {
'account_id': account_id,
'customer_name': customer_name,
'plan': 'pro',
'status': 'active',
}
agent.private_data = {
'account_id': 'ACCT-91024',
'customer_name': 'Northwind Medical',
}
agent.invoke([HumanMessage(content='Pull the account briefing.')])Multiple keys can be injected into the same tool. The values are never serialized into the model's view of the conversation.
#Build the final response inside a tool
For a greeting that contains private values, inject those values into a final tool and construct the response there. Merely mentioning a private-data key in model-written prose is not a supported substitution contract.
greeter = Agent(name='Customer Success Assistant', api_key='...')
@depends_on_private_data(arg_name='customer_name', data_key='customer_name')
@depends_on_private_data(arg_name='account_id', data_key='account_id')
@greeter.toolify(final_tool=True)
def welcome_customer(customer_name: str, account_id: str) -> dict:
return {'message': f'Welcome, {customer_name}. Your account is {account_id}.'}
greeter.private_data = {'customer_name': 'Acme Co', 'account_id': 'ACCT-77342'}
response = greeter.invoke(
HumanMessage(content='Welcome the customer.'), force_final_tool=True,
)
print(response.result)The final result contains the private values for the recipient. Apply your application's access controls before displaying or storing it.
#RedactedMessage — redact incoming messages
When the user's message contains sensitive content that you don't want the LLM to see, wrap it in a RedactedMessage. This requests runtime PII detection and replacement before model processing. It does not redact the message locally before sending it to the mAIvn service:
from maivn.messages import RedactedMessage
response = agent.invoke(
[RedactedMessage(content=(
'Please look up case CASE-2026-7781 for dana.lee@example.com '
'(phone +1-415-555-0199) and acknowledge receipt.'
))],
)PII detection covers email, phone, SSN, credit cards, IP addresses, and several other categories out of the box, each paired with a structural check to reduce false positives. Detected values are held within the runtime and substituted back only where it's safe to do so (e.g. inside the final tool's structured output, not in the free-form LLM trace). Detection is a safety net, not a guarantee — pair it with @depends_on_private_data and known_pii_values for values you already know are sensitive.
#Tool-result PII protection
The runtime also checks tool results for private values and detected PII before model processing. Detection can miss values; explicitly register known secrets rather than relying on a pattern match:
from maivn.messages import RedactedMessage
profile_agent = Agent(name='Contact confirmation', api_key='...')
@profile_agent.toolify(name='fetch_customer_profile')
def fetch_customer_profile(case_id: str) -> dict:
# Simulated DB row — these values were NOT in the user message
return {
'case_id': case_id,
'customer_name': 'Dana Lee',
'email': 'dana.lee@example.com',
'phone': '+1 (415) 555-0199',
'ssn': '321-54-9876',
}
@profile_agent.toolify(name='confirm_contact', final_tool=True)
def confirm_contact(case_id: str, confirmation_note: str) -> dict:
return {'case_id': case_id, 'confirmation_note': confirmation_note, 'status': 'ok'}
response = profile_agent.invoke([RedactedMessage(content=(
'Look up case CASE-2026-7781 and acknowledge receipt. In the '
'confirmation_note, include the email and phone from the lookup.'
))])The email and phone returned by fetch_customer_profile are detected by the runtime, masked when the next LLM turn sees them, but substituted back into the final tool's arguments and the user-facing response — so the round trip works end-to-end without leaking raw PII into the model's intermediate reasoning.
#Known PII values — explicit list
If you have values you know are sensitive (and might not match the auto-detector's categories), declare them up front on the RedactedMessage via known_pii_values:
from maivn.messages import RedactedMessage
response = agent.invoke([
RedactedMessage(
content='Acknowledge receipt and reference the internal case.',
known_pii_values=[
'INTERNAL-CASE-7782',
'project-coastal-shield-rev2',
],
),
])known_pii_values accepts raw strings as well as PrivateData descriptors. These get the same treatment as auto-detected PII — masked in the LLM context, substituted back only in safe spots.
#What's next
- Private Data guide — the deeper treatment, including the whitelist model and how access to private values is tracked.
- Memory — combining memory retrieval with private-data workflows.