hiflo/Flo · Safety & boundaries

Boundaries, enforced.

An AI inside an HR system needs hard boundaries — not soft ones in a prompt. Flo's are enforced in the architecture, not the policy document.

RLSrow-level security · postgres
0data retention · llm api
alltool calls · logged · replayable
The rules

Eight commitments. Live.

01
Tools run as the user, not as Flo

Every tool call inherits the asking employee's permissions. Flo can't see records you can't see. The audit log records you, not Flo. There is no shared service account behind the curtain.

02
Write actions need confirmation by default

Submitting leave, sending an email, generating a SARS form — Flo proposes, you confirm. Admins can elevate specific tools to auto-confirm within stated policy.

03
Flo will not make sensitive HR decisions

Performance ratings, salary changes, hiring decisions, terminations — Flo can draft, summarize, and prepare. The decision sits with you, with evidence and calibration.

04
No training on customer data, ever

We use frontier LLMs with zero-retention API access. Customer prompts and responses are never used for training — by us, our providers, or anyone downstream. Contractually committed in our DPA.

05
Anonymity is enforced at the row level

When Flo summarizes survey themes, it cannot reach back to who said what. The boundary is enforced in the database with row-level security, not in a prompt.

06
Per-tenant tool disablement

Don't want Flo touching payroll? Turn off the tool group. Don't want auto-approvals? Turn them off. Granular, per-customer, in plain settings.

07
Replayable reasoning

Every multi-step interaction has a trace. You can see what Flo retrieved, which tools it called, and why. Replay the same context against a future model to compare.

08
Rate limits and circuit breakers

No single user, tool, or tenant can run away with Flo. Per-tool rate limits. Anomaly detection. Auto-pause on spikes, with admin notification.

Architecture

Boundaries live in the schema.

A prompt that says "don't see other tenants" is theatre. A postgres RLS policy that physically can't return another tenant's rows is engineering.

Every table is scoped at the row level by tenant_id and, where relevant, by employee_id. Flo's tool layer sets the connection user to the asking employee before any query runs. No tenant_id parameter is needed because no tenant_id parameter is trusted.

-- every table has rls on
CREATE POLICY tenant_isolation ON employees
USING (tenant_id = current_tenant());
-- and employee-scope for sensitive tables
CREATE POLICY own_record ON leave_balances
USING (employee_id = current_employee()
OR can_see_team(current_employee(), employee_id));
-- flo's tool wrapper sets the actor
SET LOCAL hiflo.actor = 'emp_4218';
SET LOCAL hiflo.tenant = 'tnt_norfolk';
The thing that sold us was the audit log. Every Flo action recorded as me, not as Flo. We knew where the responsibility sat.
Khanyi Mahlangu·COO·Quill Studios

Quiet doesn't mean loose.

See Flo's full architecture in our Trust Center, or talk to our team.