Skip to main content
connic
Back to BlogTutorial

Control Data Access in connic Apps and Agents

Access rules in connic limit what app visitors and AI agents read and change, see the same visitor in child agents, and replace older agent settings.

November 7, 20268 min readAuthor: connic engineering

In connic, apps and agents write access rules the same way. An app's rules decide what a visitor's browser may read and change. An agent's rules decide what its built-in database, file, and Retrieval tools may do. When an app visitor started the run, the agent's rules can limit it to that visitor's records, and the agents it calls see the same visitor in their own rules. This tutorial sets up both for a customer portal and moves agents off the older database, retrieval, and files settings.

One rule language, two defaults

Rules sit under access in apps/<key>.yaml or agents/<name>.yaml. Each rule belongs to a resource, such as a database collection, a files folder, or a Retrieval namespace, and to an operation. It holds an expression about who asks and about the record, written in connic's expression language, the same one that approval rules and conditional tools use. Database and files rules have the same operations in apps and agents. In Retrieval, apps can only search, while agents can also store and delete. Only apps have rules for runs, sessions, and approvals.

The two differ in what happens without rules:

Apps: closed by default
The rules check every request the browser sends to the data API. An app without access can't read or change any data.
Agents: open until restricted
The rules check every call of the built-in database, file, and Retrieval tools, also when the project's own tools call them through connic.tools. An agent without access or the older settings can use all data of its environment.

Once an agent has access, it is as strict as an app: a collection, folder, namespace, or operation without a rule is denied. If the agent behind an app's chat has no rules, the app shows each customer only their own orders, while the agent answers the same customer with a database tool that can read every order.

Example: an order portal

The example is an order portal for a fictional online shop. Customers sign in with the shop's own login, see their orders, upload photos of damaged goods, and ask the agent order-support questions in a chat. The chat runs through a WebSocket connector with apps_only: true. A members collection links each customer's email to a customer_id, and every order and payment carries that ID.

The app's rules use a lookup to find the visitor's entry in members and show only that customer's orders. Uploads go to the uploads folder, and set writes the visitor's ID into each file's metadata, whatever the browser sends:

apps/portal.yaml
connectors:
  - portal-chat
lookups:
  member:
    collection: members
    where: doc.email == user.email
access:
  database:
    orders:
      read: doc.customer_id == member.customer_id
  files:
    uploads:
      read: file.metadata.uploaded_by == user.id
      write: new.size <= 10000000
      set:
        uploaded_by: user.id

Orders have no insert, update, or delete rule, so the browser can't change them. Each visitor sees only the files tagged with their own ID. Sign-in, connectors, and the data API are covered in the apps announcement.

Hold the agent to the visitor's records

A chat message from the portal starts a run that carries the visitor. connic takes the visitor from the signed app request, so middleware, tools, and the message itself can't change it, and the agent's rules see it as user. The agent file gets the same lookup as the app and rules for its database tools. The file and Retrieval rules follow in the next section:

agents/order-support.yaml
name: order-support
tools:
  - db_find
  - db_count
  - db_update
  - file_list
  - file_read
  - file_write
  - retrieval_query
  - trigger_agent
lookups:
  member:
    collection: members
    where: doc.email == user.email
access:
  database:
    orders:
      read: user == null or doc.customer_id == member.customer_id
      update: user == null or doc.customer_id == member.customer_id

connic evaluates user and the lookup first and adds the rest of the rule to the tool's query. For a signed-in customer, db_find and db_count return only their orders, and db_update changes only those. Asked about another customer's order number, the agent finds nothing, as if the order didn't exist.

user == null covers runs without a visitor, such as runs from cron, a webhook, or the dashboard. They still reach every order. Without that condition, the rules deny those runs.

When a rule can't hold for any record, for example for a visitor without an entry in members, the tool call returns an access-denied error instead of a result. The run's logs record it as a warning. Every database, file, or Retrieval tool the agent lists needs rules as well: once access is set, connic lint fails for any of them whose resource has no entries, because every call would be denied.

Files and Retrieval namespaces

The same access block holds rules for the agent's file and Retrieval tools:

agents/order-support.yaml
access:
  files:
    uploads:
      read: user == null or file.metadata.uploaded_by == user.id
      write: true
      set:
        uploaded_by: user.id
  retrieval:
    help:
      search: true

The agent tags files in uploads with the same uploaded_by as the app. In the portal, a customer sees the files the agent saved for them, and the agent reads only that customer's photos. Because set reads user, runs without a visitor can't write to uploads. Without update and delete rules, the agent can't rename, move, or remove files.

In Retrieval, the agent searches help and the namespaces below it. A search without a namespace would need an entry for "*", and storing or deleting entries is denied. A search in help returns passages from namespaces such as help.internal as well, whatever their own rules say. Content for staff therefore belongs in a separate namespace, such as internal.help.

Child agents work for the same visitor

For refund questions, order-support starts the agent refund-check with trigger_agent. connic passes the visitor on to that run, so the rules of refund-check see the same user, and so do the agents it starts in turn. The rules themselves stay with each agent: refund-check applies its own access block with its own lookups.

agents/refund-check.yaml
name: refund-check
tools:
  - db_find
lookups:
  member:
    collection: members
    where: doc.email == user.email
access:
  database:
    orders:
      read: user == null or doc.customer_id == member.customer_id
    payments:
      read: user == null or doc.customer_id == member.customer_id

A child agent without access can use all data of its environment, even while it works for a visitor. Every agent that a visitor's run can reach through trigger_agent needs rules of its own. Only runs the app starts carry the visitor in end_user, so the run context of refund-check doesn't include it. If refund-check needs the customer's name for its answer, order-support passes it in the payload.

Replace the older database, retrieval, and files settings

Before access, agents limited their tools with the database, retrieval, and files settings. They are deprecated but still work: connic enforces them as access rules, and deploys warn about them in the log. An agent can't combine them with access. A typical older configuration:

agents/order-support.yaml
database:
  collections:
    orders:
      prevent_delete: true
files:
  prevent_delete: true

connic lint warns about it and prints an access block with the same behavior:

connic lint
! agents/order-support.yaml: database, retrieval and files are deprecated; replace them with:
  access:
    database:
      orders:
        read: true
        insert: true
        update: true
    files:
      '*':
        read: true
        write: true
        update: true
    retrieval:
      '*':
        search: true
        store: true
        delete: true

The block also spells out what the older settings allowed. The agent never set retrieval, so it could search, store, and delete in every namespace, and prevent_delete on files still let it write to every folder. Pasting the block in place of the old settings keeps the agent working exactly as before. A second edit then narrows it to the collections, folders, and namespaces the agent needs, with conditions on user where it works for app visitors. The access rules documentation maps each older setting to its rules.

Check runs with and without a visitor

  1. Lint the project. With composer SDK 0.1.63 or later, connic lint shows no deprecation warning and no database, file, or Retrieval tool without rules.

  2. Sign in as two customers. Use two test accounts whose entries in members point to different customers. Each sees only their own orders, in the portal and in the agent's answers. Asking about the other customer's order number finds nothing.

  3. Sign in without a member entry. The agent's database calls return an access-denied error, and the run's logs show a warning for each.

  4. Run the agent without a visitor. Started from the dashboard or by cron, order-support reaches every order, and writes to uploads are denied.

  5. Follow a child run. Ask about a refund in the portal and open the run of refund-check from the parent's trace. Its database calls return only that customer's orders and payments.

Give every customer only their own data

Build your agents and the app that calls them in one connic project, with access rules in code.

Frequently Asked Questions

Without access or the older database, retrieval, and files settings, an agent's built-in database, file, and Retrieval tools can use all data of its environment. Once access is set, anything without a rule is denied.

No. An agent started with trigger_agent sees the same app visitor as user, but applies its own access block and lookups. A child agent without access can use all data of its environment.

No. connic takes the visitor from the signed app request and passes it to child runs itself, so middleware and tools can't change it. Runs that no app visitor started have user set to null.

No. Without an app visitor, user is null, but agent rules can also use the run context and the current session, for example file.session_id == session.id to limit an agent to the files written in its current session.

Yes. They are deprecated, and connic enforces them as access rules. connic lint warns about them and prints the matching access block. An agent can't combine them with access.

Yes, when they call the built-in tools through connic.tools. The agent's rules check those calls the same way as the calls the model makes.

More from the Blog

Tutorial

Build a WhatsApp Support Agent with Twilio and connic

Connect WhatsApp to a connic agent through Twilio: keep each customer's history, route replies to the right number, and handle templates and failed sends.

November 10, 20269 min read
Tutorial

How to Deploy a Python AI Agent Without Kubernetes

A Python AI agent deployed without Kubernetes using YAML, plain Python, deployment-gated tests, Git, and a managed EU runtime. Includes working code.

August 12, 202612 min read
Tutorial

How to Trigger AI Agents from Kafka Topics

Point a connic Kafka inbound connector at a topic and every message starts an agent run. Configure the connector, link an agent, deploy, and watch runs.

July 12, 20268 min read
Tutorial

How Small Engineering Teams Can Add an AI Agent to SaaS

A practical, step-by-step path to shipping a first production AI agent with a small team: scope one job, define it in config, connect it to existing systems, and let a runtime handle the rest.

June 12, 20269 min read
Tutorial

Automated Agent Scoring: AI Agent Evaluation with LLM Judges

Automated agent scoring uses an LLM judge to grade sampled or every matching agent run against defined criteria. Track score trends and alert on regressions.

March 29, 202610 min read
Tutorial

Database vs Retrieval vs Sessions: Agent Memory Compared

A comparison of connic's Database, Retrieval, and persistent sessions, including identity, TTL, sanitized events, and runs matched to that identity.

March 4, 202612 min read
Tutorial

AI Agents: From Prototype to Production

A demo works great until 1,000 concurrent users arrive. A practical guide to the production requirements most teams find out about too late.

January 10, 202610 min read
Tutorial

AI Agents in SaaS Without an ML Team

Customers expect AI features even when a product team has no ML engineers. See how teams ship AI agents using skills they already have.

December 5, 20258 min read
Tutorial

connic RAG: Ranked Retrieval and Links to Source Files

Build a production RAG agent in connic that searches by meaning and exact terms, ranks passages by relevance, cites its sources, and links the original files.

November 15, 202512 min read