KlicForge Docs

Data tables

Structured storage your agents can read from and write to — fields, personal data handling, and per-agent permissions.

A data table is structured storage your agent can read from and write to during a conversation — like a spreadsheet the agent can use. Each table has a name, a permanent slug, typed fields (columns) and records (rows).

Common uses: leads, support tickets, orders, bookings, and anything else an agent needs to capture or look up.

Creating a table

Select Data Tables in the sidebar, then create a table and add fields. Then open the table's Permissions tab and grant your agent access — an agent cannot see a table until you do.

Field types

GroupTypes
Basictext, long_text, number, currency, date, datetime, boolean, json, url
Selectionsingle_select, multi_select, status
Identity / personal dataemail, phone, name, nric, address, whatsapp_id, telegram_id, telegram_handle
Systemauto_increment, uuid, contact_id
Structuralrelation (links to another table), asset_id (references an uploaded file)

A field's slug and type are permanent once created — they are the key its values are stored under. The table's display name, description, icon and colour can change at any time; the table's slug cannot.

Personal data and encryption

The identity field types above are treated as personal data and are automatically redacted from audit logs, whether or not the field is encrypted.

A subset additionally supports field-level encryption: text, long_text, email, phone, url, name, nric, address, whatsapp_id. Note that telegram_id and telegram_handle are personal data but cannot be encrypted.

When a field is created with encryption on:

  • Values are encrypted at rest and never returned in plaintext by default. Dashboard users and agents both see the masked form (j***@x.com, +65***4567); the real value comes back only through an explicit, audited reveal.
  • text, long_text and url have no masked form, so an agent does not see those fields at all. It can still write to them.
  • The choice is permanent. Encryption cannot be switched on or off after the field exists.

Finding an encrypted field later

An encrypted field is still findable, but only in the ways you allow. The field editor asks Finding this field later and offers three answers:

ChoiceWhat a search can find
Can't be searchedNothing. You can still test whether a record has a value at all
Exact matches onlyThe complete value — a whole email address, a whole phone number
Match any wordThe complete value, or any single word of it

Each field type arrives on the right answer, so you can usually leave this alone:

  • nameMatch any word, so searching "Sufiyan" finds "Mohammad Sufiyan Rahmat"
  • email, phone, whatsapp_id, nric, textExact matches only
  • long_text, url, addressCan't be searched

Match any word is offered on name and text only — the types whose values are made of words. It matches whole words, not fragments: "sufi" does not find "sufiyan", and there is no fuzzy matching, so "Sufyan" does not find "Sufiyan" either.

Exact matching ignores capitalisation and formatting, so [email protected] finds the record stored as [email protected], and +65 9123 4567 finds +6591234567.

Two things are never available on an encrypted field, whatever you choose: sorting by it, and range filters on it (before/after, greater/less than). Like encryption itself, the choice is permanent.

Permissions

Access is granted per agent, per table, as four gates: read, create, update, delete. Finer control — which fields an agent can see, whether it can search all rows or only its own, export limits — is set by an admin on the table's Permissions tab. It cannot be changed from a conversation.

Granting a gate is all an agent needs to use it. A read grant lets it find and open records, a create grant lets it add them, and so on — you do not have to give the agent a data skill as well. Add a skill when you want to shape how it uses the table; add it for schema changes, exports and bulk imports, which are never granted this way.

An agent with any read access can also inspect the table's structure — field names, types, which fields are required — so it knows what a valid record looks like before it tries to save one. This never exposes the contents of a record, and the Allow schema inspection checkbox lets you turn it off per table.

A field an agent cannot read is also a field it cannot search. Hiding a field therefore hides it completely: the agent cannot use a search to confirm what a record holds in a column it is not allowed to see.

Access modes

Read, write and delete each have an access mode:

ModeWho it is for
Self (own records only)Customer-facing agents — each end user only sees rows belonging to them. Requires at least one row scope rule
ScopedInternal agents limited to an admin-defined slice, e.g. one branch
TableBroad row access for trusted internal agents, still subject to field limits and per-query caps
Analytics (read only)Aggregate and count queries only; individual rows are never returned

Row scope rules

A scope rule ties rows to the person currently chatting by comparing a field against the live identity of the conversation — contact ID, WhatsApp ID, Telegram ID or handle, user ID.

  • contact_id equals the current contact ID — matches rows created for this contact.
  • whatsapp_number equals the current WhatsApp ID — matches imported rows keyed by the customer's number, including rows that existed before they ever chatted.

Scope rules are enforced on the server and fail closed: if the required identity is not available in that conversation, access is denied rather than opened up.

In dashboard test chat the identity is the logged-in operator's own contact, so a WhatsApp-keyed rule only resolves there if that contact has a linked WhatsApp number.

When a child table links to a parent via a relation field — for example policies.client_id → clients — the child can be scoped through the parent, so you do not have to copy the customer's identity onto every child row.

Read the rule as: allow a child row when its relation points at a parent row owned by the person currently chatting. A customer asking "show my policies" has their client record found by WhatsApp number, and only policies linked to that client are returned.

Constraints:

  • The relation must be a single-value relation. Multi-value relations cannot be used for scoping, and the dashboard rejects invalid configurations when you save.
  • When the person matches exactly one parent record, the relation is stamped automatically on create — the agent cannot point a row at someone else's parent record.
  • Matching no parent record returns zero rows, not an error.
  • Matching several parent records means the agent must specify which one when creating.

Revealing an encrypted value

A mask is enough to recognise a record and talk about it, but not enough to phone anyone. When an agent genuinely needs the real value — to call a lead, email a quote, or confirm two records are the same person — it can reveal it, and both of these must be true:

  1. The agent has the Reveal Encrypted Field tool, or the Data Tables: Reveal PII skill that carries it.
  2. The table's access settings have Allow reveal of encrypted fields ticked for that agent.

The second switch is off on every table and every access preset until you tick it. With one of the two missing, the agent tells the person the value is available in the dashboard and stops.

A reveal returns the real values for one record at a time, and every field it returns is written to the table's audit log with the agent that asked. Fields you have read-blocked stay blocked here — asking for the real value is not a way around a restriction you already set.

Revealing is for showing a value, not for moving it. The agent can read it out to you, but it cannot pass it on: not into a second record, not into a message it sends, not into a connected app. Asking it to do any of those gets a refusal rather than a silent failure, so if a value needs to end up somewhere else, put it there yourself. The agent does not receive the value either — it writes its reply around a placeholder that KlicForge fills in afterwards, so what reaches the model provider is the placeholder. See AI providers.

Do not give this to a public widget agent, a customer-facing WhatsApp or Telegram agent, or any agent on a Self-mode table. Masking is what lets those agents be useful without holding real personal data. It is for internal operator agents — sales follow-up, support triage, back-office lookups.

Adding records

Records can be created by an agent during a conversation, added manually in the dashboard, or brought in from a file — an agent can preview and import records from an attached spreadsheet.

When a write is rejected

A record that fails validation is reported back to the agent field by field: which field, why, and for a choice field, the values it accepts. An agent can then ask the contact one specific question rather than guessing. If it keeps failing the same write, it stops after three attempts and says what it could not do instead of retrying until it runs out of steps.

Two things make rejections less likely in the first place: required fields and formats are visible to the agent before it writes, and fields the agent is not permitted to see are never named in an error. How much of the field list an error names depends on Allow schema inspection: with it on, a rejection lists every valid field slug; with it off, the agent is told to ask for the structure instead. This applies to single-record writes and to importing many records at once — a batch import now validates every record before writing, the same as a single one, instead of accepting a malformed record and only failing later.

One rejection cannot be recovered from in the conversation: a choice field with no options set accepts no value at all. The agent is told the field needs options rather than being handed a value to guess at, and it will not create a choice field that way itself — add the options on the table's Fields tab. See field types.

Protecting personal data from the agent

Blocking a field prevents both reading and writing it. If you want an agent to capture personal data but never read it back — the right default for a public-facing agent — restrict it on read only. Fields like contact name, email, phone and messaging IDs should be read-blocked on any agent the public can talk to.

A read-blocked field cannot be revealed either, even on a table where reveal is allowed.

Was this page helpful?

On this page