# ERP.net Operator — Complete Documentation Operator is an AI agent and app building platform for ERP.net. AI agents work with your business data, answer questions and take action; Digital Entities run always-on with memory and their own work rhythm; the App Builder turns conversations into working business apps. Source: https://operator.net/help ## What Operator is ERP.net Operator is an operational AI platform for companies running ERP.net. It is not a chat assistant bolted onto a website: it queries live business data, performs work in the systems the company already uses, and keeps watching processes over time. Who it is for: ERP.net customers — management, sales, operations, finance and customer service teams — who want AI applied to everyday operational work. What it changes: - Less routine work: repetitive queries, checks and data entry are handled by AI. - Faster decisions: answers come straight from business data, without waiting for a report. - Nothing important gets missed: deadlines, exceptions and missed actions are watched continuously. - Faster adaptation: new workflows and small business apps appear in days. The platform has four building blocks: 1. Intelligent Workspace — one chat across business systems; ERP.net connected out of the box, other systems through MCP. 2. AI Agents — role-based agents that follow the company's procedures and can run unattended on triggers, schedules, webhooks and events. 3. Digital Entities — always-on agents with long-lived memory, their own task list and their own work rhythm; they notice what happened and what failed to happen. 4. App Builder — custom business apps described in natural language, built on the ERP.net data model. --- # Operator.net *AI platform for business operations.* Operator is a workspace where AI agents work with your business data. It understands your operations, answers questions, and takes action on your behalf. Any system can be wired in through MCP and web requests — and [ERP.net](/help/erpnet-overview) is supported natively, with deep knowledge of its data model, security, and documents. Think of it as an operator for your business: one chat that can reach across systems, run processes, and build tools when you need them. **Operator knows itself.** You do not have to read the whole documentation to get started — just ask Operator. It can explain its own features: how agents work, what an app can do, how to set up a schedule. In practice, the fastest way to learn Operator is to ask it about itself. **See working examples.** Want ideas? Browse the [Examples gallery](https://operator.net/examples) — a set of ready-made demo apps, such as an online shop, a door configurator, and a service dispatch board. Each one opens live. The demos use sample data and are not connected to a real ERP instance. Inside Operator, the gallery is always at hand: open your profile menu, hover **Build**, and choose **View Examples Gallery**. The public address above shows the same gallery without signing in. ## The four pillars **Intelligent Workspace** — One place to ask, act, and get answers across your business systems. Start typing in natural language and let the built-in agents handle the rest — from ERP lookups to multi-step tasks. [Meet the built-in agents →](/help/built-in-agents) **AI Agents** — Build specialized agents for a role or workflow, then use them in chat, on the phone as voice agents, or on autopilot with schedules, webhooks, and email triggers. [Explore agents →](/help/agents) · [Set up automations →](/help/automations) · [Set up voice →](/help/speech-setup) **Digital Entities** — Always-ON agents that watch for events, remember what matters, keep their own task list, and wake themselves up when something needs attention — including when an expected reply never arrives. [Explore Digital Entities →](/help/digital-entities) **App Builder** — Create custom apps and dashboards in natural language, backed by your ERP.net data model. Run them inside Operator, full-screen, embedded in the ERP.net Web Client, or publish them as part of a community package. [Explore the App Builder →](/help/app-builder) ## Where to start - [What You Can Do with Operator](/help/what-you-can-do) - [Getting Started](/help/getting-started) - [First Commands to Try](/help/first-commands) - [UI Overview](/help/ui-overview) ## Core capabilities - [ERP.net Integration](/help/erpnet-overview) - [Community Sharing](/help/community) - [Agent Delegation](/help/agent-delegation) - [Version History & Restore](/help/version-history) - [Instance Permission Policies](/help/permission-policies) - [Notifications](/help/notifications) --- # Getting Started *Connect your ERP.net instance and start exploring* Operator works best when connected to your ERP.net instance. While you can explore documentation and entity schemas without a connection, querying data, managing records, and most powerful features require an active instance connection. ## Prerequisites Before users can start using Operator, two things need to be configured at the instance level: ### 1. Enable Domain API Your ERP.net instance must have its **Domain API** properly configured and activated. The Domain API is the OData v4–based REST interface that Operator uses to query and manage data. If it's not enabled, Operator won't be able to communicate with your instance. > Contact your ERP.net administrator or hosting provider if you're unsure whether Domain API is active on your instance. ### 2. Install Operator from the Marketplace An administrator must install the Operator app on the ERP.net instance through the **ERP.net Marketplace**: 👉 [Install Operator from the Marketplace](https://marketplace.erp.net/apps/operator) Once installed, individual users can connect to the instance from within Operator. --- ## Connecting Your Instance After the prerequisites above are in place, you'll need your instance name—the subdomain from your ERP.net URL. ### Finding Your Instance Name Your instance name is the first part of your ERP.net URL. For example: ``` https://demodb.my.erp.net ``` In this example, `demodb` is the instance name you'll enter when connecting. ### Step-by-Step Connection 1. **Open the Instance Selector** — Click on the instance button in the header (or "Connect Instance" if no instance is connected). 2. **Add a New Instance** — Click "Add Instance" to open the connection dialog. 3. **Enter Your Instance Name** — Type your instance name (e.g., `demodb`). The display name will auto-generate, but you can customize it. 4. **Choose Connection Type** — Select whether you're connecting as an **Internal User** (team member) or **Client** (external customer). This determines which capabilities are available. 5. **Authenticate** — Click "Add Instance" to be redirected to ERP.net's login page. Sign in with your ERP.net credentials to authorize the connection. 6. **Start Using Operator** — Once connected, you'll be returned to Operator with full access to your instance data. ### Connection Types | Type | Description | |------|-------------| | 🧑‍💻 Internal User | For employees and partners. Access to full Operator capabilities including data queries, data updates, and internal tools. | | 🏢 Client | For external customers. Access to Client Advisor capabilities: products, pricing, orders, and billing—focused on B2B/B2C self-service. | > You can maintain both connection types for the same instance if you need to switch between internal and client perspectives. ## What You Can Do Without an Instance Even without connecting an instance, you can: - **Search Documentation** — Explore ERP.net features, workflows, and guides - **Explore Entity Schema** — Understand the data model, entities, and relationships - **Browse Marketplace** — Discover apps and integrations - **Search Knowledge Base** — Find answers to common questions ## Example Prompts Here are some examples to get you started. Try typing these (or similar questions) in the chat: ### Documentation & Learning - "How do sales orders work in ERP.net?" - "How do I configure multi-currency?" ### Schema Exploration - "What fields does the Customer entity have?" - "Show me the SalesOrder entity structure" ### Data Queries (requires instance) - "Show me all pending sales orders" - "Find customers from Germany" ### Update Data (requires instance) - "Create a new customer named Acme Corp" - "Update product SKU-123 price to $99.99" ### Client Advisor (client mode) - "Search for wireless headphones" - "Show my recent orders" ## Enterprise Context If your ERP.net instance has multiple enterprise companies, you can select which one to work with. Click on the company name in the header to switch between enterprise companies and locations. The enterprise context affects all data queries and record operations, ensuring you're always working with the right company's data. ## Next Steps - Explore [What You Can Do with Operator](/help/what-you-can-do) to see what you can build - Set up [Agents](/help/agents) for scheduled or triggered workflows - Review [URL Parameters](/help/url-parameters) for embedding and deep linking --- # Built-in Agents *The agents that ship with Operator* Operator ships with three built-in agents available to every user. Pick one from the agent selector based on what you need to do — each has full knowledge of ERP.net and access to the tools appropriate for its role. ## Advisor Knows everything about ERP.net: features, configuration options, best practices, pricing, and how things fit together. Use it to **learn about the system** or get guidance before taking action. - Read-only — does not change anything in your instance. - Available **without an instance connection**, so it works even before you connect. - Best for: "How does X work?", "What's the right way to configure Y?", "Which module covers Z?" ## Business Specialist The everyday workhorse. Reads and updates business data, manages documents, schedules meetings, sends mail, and handles routine operations across sales, purchasing, HR, finance, and any other business role. - Acts on your instance — creates, updates, and processes real records. - The **default choice for getting things done**. - Best for: "Find this customer's open orders", "Create an invoice for…", "Schedule a follow-up for next Tuesday", "Reply to this email and log it on the case". ## System Architect For **Power Users and above**. Configures custom logic, workflows, settings, and specialized behavior. Solves complex business problems and designs how your instance works. - Use it when you need to change **how** the system works, not just the data inside it. - Best for: "Add a validation rule for…", "Configure a workflow that…", "Design a custom process for…". ## Choosing an agent A simple rule of thumb: | You want to… | Use | |---|---| | Learn or get guidance | **Advisor** | | Operate the business | **Business Specialist** | | Configure how the system works | **System Architect** | You can build your own agent on top of any of these. See [Agents](/help/agents) for how to create custom agents tailored to your workflows. --- # First Commands to Try *Don't know where to start? Pick a built-in agent and try one of these.* The best way to learn Operator is to ask an agent to do something real. Below are starter prompts for each [built-in agent](/help/built-in-agents) — copy one, tweak it to your context, and send. > Tip: agents act on the connection you have selected. Make sure the right instance is active before sending commands that touch data. ## Advisor Use the Advisor when you want to **learn** about ERP.net before doing anything in your instance. - "What's the difference between a sales order and a sales invoice?" - "How do I configure a new VAT rate?" - "Which module handles consignment stock?" - "Walk me through the standard purchase-to-pay flow." - "What are the licensing options for ERP.net?" - "How does the document state machine work?" ## Business Specialist Use the Business Specialist for **everyday operations** — looking up records, creating documents, scheduling, mailing, and finishing routine work. ### Look things up - "Show me my open sales orders for this week." - "Find the customer 'Acme Corp' and list their last 5 invoices." - "Which products are below the minimum stock level?" - "What payments are overdue by more than 30 days?" ### Create and update records - "Create a sales quote for Acme Corp with 10 units of product X." - "Add a new contact 'Jane Doe' to customer Acme Corp with email jane@acme.com." - "Mark invoice INV-2026-001 as paid." ### Schedule and communicate - "Schedule a call with John from Acme Corp next Tuesday at 10:00." - "Draft a friendly reminder email for invoice INV-2026-001 and send it to the customer." - "Summarize today's calendar and flag anything that overlaps." ## System Architect Use the System Architect (Power Users and above) when you want to change **how the system behaves**, not just the data inside it. - "Add a validation that prevents saving a sales order without a delivery date." - "Design a workflow that routes purchase orders above 10,000 EUR for approval." - "Suggest a custom entity for tracking equipment service contracts." - "Review my current document types and recommend which ones can be retired." - "Help me model a discount policy that depends on customer category and product group." ## App Builder Use the [App Builder](/help/app-builder) (Power Users and above) to create small, focused ERP data apps with natural language. ### Dashboards and monitors - "Create a dashboard showing overdue invoices grouped by customer." - "Build a screen that shows products below minimum stock with a red warning badge." - "Make a kanban-style board of my open sales opportunities by stage." ### Data entry and lookup - "Build a form for quickly logging customer calls with notes and follow-up date." - "Create a lookup screen that finds customers by phone number and shows their last 10 orders." - "Make an app that lets me scan a product code and see real-time warehouse quantity." ### With AI inside the app - "Add a chat panel where the user can talk to the Business Specialist about the selected customer." - "When the user uploads an invoice photo, use AI to extract the total and invoice number." - "Add a button that summarizes the selected sales order notes into one paragraph." ### Iterate and refine - "Add a date range filter to the dashboard." - "Make the table sortable by amount." - "Add a bar chart next to the table showing monthly totals." - "Let the user export the current view to CSV." ## What next? - Try the same task with two different agents and compare the results. - When you find a prompt that works well, save it as a **greeting button** on a custom agent — see [Creating Agents](/help/agents-creating). - Explore [Working with the UI](/help/ui-overview) to learn the interface around the chat. --- # What You Can Do with Operator *Start from the problem, not from the feature* Most help pages explain how a button works. This section answers a different question: **what can you actually achieve with Operator, and what does it take to get there?** Everything in Operator comes down to four kinds of result. | Outcome | What it means | Read | |---|---|---| | **Answer and advise** | An agent that looks things up in your data and documentation, explains, drafts and replies. | [Answer and advise](/help/what-you-can-do-answer) | | **Watch and act** | An agent that runs on its own — on a schedule, on an incoming email, on an event — and takes action. | [Watch and act](/help/what-you-can-do-watch-act) | | **Build apps for your team** | A screen or tool built in natural language, running on your live business data. | [Build apps for your team](/help/what-you-can-do-apps) | | **Publish to the outside world** | A page anyone can open — no login, no account. | [Publish to the outside world](/help/what-you-can-do-public) | ## Playbooks: problems and the solution you can build Each playbook is a complete recipe — the problem, what you end up with, what it needs, and the exact steps (including what to type) to build it. | The problem | Build this | |---|---| | Supplier or competitor prices change and nobody notices until margin is gone. | [Price-watching agent](/help/playbook-price-watch) | | The same customer questions arrive by email fifty times a week. | [Email answering agent](/help/playbook-email-answering) | | Customers phone to ask "can I get it in this size, this colour, what does it cost?" | [Product configurator website](/help/playbook-configurator) | | Salespeople on the road can't see stock, prices or customer history. | [Mobile sales app](/help/playbook-mobile-sales) | | A salesperson is driving and can't type an order or a visit report. | [Voice sales executive](/help/playbook-voice-sales) | | Overdue invoices pile up because nobody has time to chase them. | [Overdue invoice chaser](/help/playbook-invoice-chaser) | | Approval requests get lost in email threads. | [Approvals desk](/help/playbook-approvals-desk) | | Field technicians report time and materials on paper. | [Field service check-in app](/help/playbook-field-service) | | Management asks for numbers that take a day to assemble. | [Management cockpit](/help/playbook-management-cockpit) | ## How much work is any of this? Almost all of it is conversation. You describe the outcome to the [Agent Builder](/help/agents-creating) or the [App Builder](/help/app-builder); it builds, you test, you correct. A simple agent is minutes. A working app is usually one sitting. The playbooks say honestly which ones need a [Pro app](/help/pro-apps), which need a connected [ERP.net instance](/help/instance-connections), and which need nothing but an agent. ## Not sure which one fits? Ask the **Advisor** agent in plain words — *"prices from my suppliers keep changing, can Operator help?"* The Advisor searches this documentation, including every playbook here, and will point you at the right recipe and walk you through it. --- # Answer and advise *Agents that look things up, explain, draft and reply* This is the outcome most people meet first: you ask a question in plain language and get a real answer, grounded in your own data and documentation rather than in guesswork. ## What an agent can look things up in ### Your business data **Requires a connected instance** — An agent can read anything in your ERP.net instance: customers, orders, products, stock, invoices, documents. It translates your question into Domain API calls by itself. It can also produce **summaries and totals** — counts, sums, minimums and maximums, breakdowns per customer, product or month — computed on the server across all matching records rather than a single page. See [Working with Data and Business Objects](/help/erpnet-data-operations). Agents can also explore the **data model** itself: which entities exist, their fields, and how they relate. This is what lets an agent answer a question it has never seen before. ### Product documentation Deep semantic search over the ERP.net documentation — Technical, Developer, Presales, Web Client and Windows Client. When the agent finds a relevant page, it returns the full page (when short) or a window of surrounding sections around each match. This is the right source for conceptual questions: *how does X work*, *explain Y*, multi-step workflows, and syntax or API references. ### Everything at once A broad hybrid search across the whole knowledge corpus in a single call: official documentation, the knowledge base, system business rules, **Operator's own documentation** (including every playbook in this section) and each companion app's docs. It returns lightweight previews so the agent can cast a wide net, then read the promising hits in full. ### Past conversations Agents can search your earlier conversations with Operator, which is how they pick up context from work you did last week. ### Internal knowledge **Internal** — Employees can additionally search past support tickets and internal development cases. ### Marketplace Search apps, extensions and integrations from the ERP.net Marketplace to find something that already solves your problem. ## What an agent can do with the answer - Explain it, in your language, at the level you ask for. - Draft a reply, an offer, a summary, a report. - Create a **support ticket** when the issue genuinely needs a human, and track its status afterwards. - Hand part of the job to a specialised sub-agent you built, and combine the results — see [Delegation & Sub-Agents](/help/agent-delegation). ## Answering your customers **Client Advisor mode** turns this outcome outward: your own customers get a self-service assistant against your instance. It can search your product catalogue, show pricing and active promotions with customer-specific terms, manage a shopping cart, show order history and delivery status, and show invoices, payments and outstanding balances. These abilities exist only in Client Advisor mode — an internal agent never gets them by accident. ## What it takes | You want | You need | |---|---| | Answers from documentation | Nothing — works out of the box | | Answers from your business data | A connected [ERP.net instance](/help/instance-connections) | | A dedicated persona with its own rules | An [agent you create](/help/agents-creating) | | Customer-facing self-service | Client Advisor mode | ## Playbooks that use this - [Email answering agent](/help/playbook-email-answering) - [Management cockpit](/help/playbook-management-cockpit) - [Voice sales executive](/help/playbook-voice-sales) ## When the answer is numbers Ask for a breakdown, a trend or a comparison and the agent can draw it right in the conversation — KPI cards, charts and a table. See [Visuals in Answers](/help/dashboards-in-answers). --- # Visuals in answers *Agents can draw the numbers — and explain how things connect* Every agent that can draw an in-chat dashboard can also add a diagram when it makes an answer easier to understand. The visual is part of the message, next to the agent's written explanation. ## What you can ask for For numbers across categories or over time, ask for a dashboard: - *"Show me turnover by month for this year, with a trend and the totals."* - *"Compare open cases per team for the last quarter — chart it."* - *"Top 10 customers by revenue this year, as a dashboard with the share of the top three."* For a process, relationship, architecture, sequence, state or timeline, ask for a diagram: - *"Show how a sales order moves from draft to invoicing."* - *"Explain the relationship between customers, orders and invoices with a diagram."* - *"Draw the approval flow and show where each team acts."* You do not have to name a visual. When an answer describes a process, flow, sequence, state change, relationship, architecture, dependency or timeline, the agent leans toward adding a compact diagram when it makes the path or connections easier to grasp. Simple explanations remain text only. You can still say *"as a line chart"*, *"show the process"*, or *"plain text only"*. ## What you get - **KPI cards** for headline figures — total, average, best month, change. - **Bar and line charts** for breakdowns and trends. - **Doughnut charts** for shares of a whole. - **A table** when the exact rows matter. - **A process or sequence diagram** for steps and interactions. - **A state or relationship diagram** for statuses, dependencies and structure. - **A timeline** for ordered milestones. Visuals follow your theme, work on a phone, and stay in the conversation. You can pan and zoom a diagram, fit it to the available space, open it full-screen, copy its source, or download it as a PNG. Diagram controls sit in their own slim row, so they do not cover steps or connections. A sequence of about five or more stages is a strong candidate for short alternating rows stacked as a snake. This uses the conversation width without turning the diagram into one long row or a very tall column. Short processes may remain in one row, while processes with real branching, convergence, or hierarchy usually use a top-to-bottom layout. Process steps usually show a short bold name with one line of detail underneath. At each turn, the arrow connects the last card of one row directly to the first card of the next row, so the sequence remains unambiguous. The diagram is displayed in the layout the agent generated; Operator does not rewrite it automatically. Agents can also choose colors from Operator's accessible chart palette when color helps distinguish categories. For example, ask: *"Show revenue by product as a colorful bar chart, and keep the same color for each product in the share chart."* The agent cannot supply arbitrary colors, so every chart continues to work in both light and dark themes. ## Records, statuses and timelines The same dashboard can also show everyday ERP shapes: - **Record cards** — a few specific records at a glance: name, a status badge, key fields, and a link to open it in ERP.net. When the retrieved data confirms that one document is the parent of another, arrows connect the cards from parent to child. - **Status stepper** — where one document stands: order, delivery, invoice, payment, with the current step highlighted and dates under finished steps. - **Comparison** — this period next to the previous one, with the change and a tiny trend line. - **Timeline** — dated milestones such as a delivery schedule or payment plan, with overdue points marked. For ERP.net document states in Bulgarian, visuals use the standard names: **Нов**, **Планиран**, **Твърдо планиран**, **Пуснат**, **Завършен** and **Затворен**. Try: - *"Where is sales order 4711?"* - *"Show order 4711 and the documents created from it."* - *"Show me the three overdue invoices of Acme."* - *"Compare turnover this month with last month."* - *"What is the payment plan for contract 88?"* ## Good to know - Every figure comes from data the agent actually retrieved. If it cannot get the data, it says so rather than drawing something. - Each answer carries **one** dashboard, with the written explanation around it. - An answer may include both one diagram and one dashboard when the diagram explains the flow and the dashboard explains the figures. For example: *"Show our order-to-cash process, then chart this quarter's volume at each completed stage."* - These are visuals for one answer, not a saved BI dashboard or an editable process model: there are no filters, no drill-down and no automatic refresh. To change the view, ask the next question. - Inside apps built with the App Builder and in background runs, agents do **not** send these visuals — the containing experience owns its presentation. --- # Watch and act *Agents that run without you and change something* An agent does not have to wait for you to type. It can wake up on a schedule, react to an incoming email, respond to an event in your instance, or be called by another system — and then do something about what it finds. ## What can wake an agent up | Trigger | Typical use | |---|---| | **Schedule** | Every morning at 07:00, every Monday, first of the month. | | **Incoming email** | An agent follows a mailbox and reacts to what arrives. | | **Event in your instance** | A document changes state, a record is created. | | **Webhook** | Another system calls Operator when something happens there. | | **Always-ON** | A [Digital Entity](/help/digital-entities) wakes itself when something needs attention — including when an expected reply never arrives. | Every wake-up is recorded in the **Events** list, whatever woke the agent — a schedule, an incoming email, an instance event or an outside call. If a wake-up produced no run, the entry says why. The same occurrence is never run twice, even if it is delivered twice. Example: a schedule set to "every weekday at 08:00" adds one event each weekday morning, and from that event you can open the run it started. See [Automations](/help/automations) for the mechanics and [Activation triggers](/help/agents-triggers) for setting triggers on an agent. ## What an agent may change ### Records in your instance **Requires a connected instance · Destructive** — Create, update and delete records: customers, orders, products, and any other entity. Deleting and other destructive operations pause for your confirmation before they run. ### Documents **Requires a connected instance** — Search document types, change document states, void documents, produce printouts, and manage the enterprise company context a document operation runs in. ### Files and attachments **Requires a connected instance** — List, retrieve and attach files to any ERP.net object, and organise objects in folders. ### Calendar **Requires a connected instance** — View, create, update and cancel appointments and meetings. ### Email An agent can send and reply to email. Every message an AI agent sends identifies itself as AI — see [AI Disclosure in Email](/help/ai-email-disclosure). ## Watching the instance itself **Requires a connected instance** — Agents can monitor performance metrics, active sessions, system messages, running procedures and configuration parameters, and read license keys, subscription plans and subscription status. This is what makes an unattended "watch my system overnight" agent possible. **Internal** — Employees additionally get customer subscription lookups by UIN or name, and hosting infrastructure queries across instances, app servers and database servers. ## Staying in control - Destructive actions wait for approval unless you explicitly allow them. - [Permission policies](/help/permission-policies) limit what an agent may read and change, per instance, independently of ERP.net rights. - Every unattended run is recorded — you can open it and see exactly what the agent did and why. ## What it takes | You want | You need | |---|---| | An agent that runs on a schedule | An agent with an activation trigger, Power User or above | | An agent that reads your mailbox | A connected mailbox on the agent | | An agent that changes ERP data | A connected instance and the matching permissions | ## Playbooks that use this - [Price-watching agent](/help/playbook-price-watch) - [Overdue invoice chaser](/help/playbook-invoice-chaser) - [Email answering agent](/help/playbook-email-answering) --- # Build apps for your team *A screen built in a conversation, running on live data* Not everything should be a chat. When a job repeats — pick a customer, see their open orders, record something — a small purpose-built screen beats typing the same request every day. The [App Builder](/help/app-builder) creates those screens from a description. You say what you need, it builds, you look at it and correct it. ## What an app can be - A form your colleagues fill in instead of sending emails. - A list with search and filters over live instance data. - A dashboard of numbers that refresh themselves. - A phone-sized tool for people who are not at a desk. - A small tool that calls another system and shows the result. Apps read and write your ERP.net data through the same secured path agents use, so they respect the same permissions. ## Who can open an app Each app has an access mode: - **ERP.net internal user** — anyone signed into the connected instance. This is the default when an instance is connected. - **Operator user** — people with an Operator account you shared it with. - **Public** — anyone with the link, no login. See [Publish to the outside world](/help/what-you-can-do-public). You can also share individual apps with named people and control whether they may only run it, design it, or own it — see [Sharing Apps](/help/app-sharing). ## Where an app runs Inside Operator, full-screen on its own address, installed on a phone as a home-screen app, or embedded in the ERP.net Web Client. Same app, no rebuild. ## What Pro adds Free apps are screens over your existing data. [Pro apps](/help/pro-apps) get a managed backend of their own: | Service | What it gives you | |---|---| | [File storage](/help/pro-apps-files) | Templates, configuration, generated reports the app can read and write. | | [Table storage](/help/pro-apps-tables) | The app's own records — drafts, settings, favourites — when they don't belong in ERP. | | [Secrets](/help/pro-apps-secrets) | API keys the app uses without ever exposing them in the app itself. | | [Web requests](/help/pro-apps-requests) | Calls to other systems, defined and tested in the Builder. | | [Pages](/help/pro-apps-pages) | Several destinations in one app, each with its own access mode. | | [Procedures](/help/pro-apps-procedures) | Server-side steps for things the browser must not do — custom sign-ins, secret checks, combined lookups. | Apps can also use AI directly — see [AI in Apps](/help/app-builder-ai) — so a screen can summarise, classify or draft, not just display. ## What it takes | You want | You need | |---|---| | An internal tool over your data | App Builder access (Power User or above, or Power User in the instance) | | Its own storage, secrets or outside calls | A [Pro](/help/pro-apps) app | | A phone app | Nothing extra — install any app to the home screen | ## Playbooks that use this - [Mobile sales app](/help/playbook-mobile-sales) - [Approvals desk](/help/playbook-approvals-desk) - [Field service check-in app](/help/playbook-field-service) - [Management cockpit](/help/playbook-management-cockpit) --- # Publish to the outside world *A page anyone can open — no login, no account* A Pro app can be published so that anybody with the link can use it: a product catalogue, a configurator, a booking form, a status lookup, a small marketing site. Visitors need no Operator account and no ERP.net user. ## How it works Pages in a Pro app each carry their own access mode. Set the home page — or the whole app — to **Public** and it becomes reachable to anonymous visitors. Everything after the app address is page and sub-page routing, so a public app behaves like an ordinary website. See [Pages](/help/pro-apps-pages). ## The rule that matters **A public page never touches your data directly.** An anonymous visitor has no instance, no session and no permissions, so the app cannot query ERP, tables, files or secrets on their behalf. Instead, you define a **[web request](/help/pro-apps-requests)** in the Cloud tab and mark it public. That request runs on the server with its own stored credentials, returns only what you chose to expose, and is the only door the public page can knock on. You decide exactly what leaves the building: a price, a stock indicator, a product list — never the whole table. The App Builder can create those requests for you, including asking you for the one secret it needs and opening the form so you only paste the value. ## What you can publish today - A catalogue or price list drawn from live data. - A configurator that prices a combination and captures the enquiry. - A form that writes an enquiry, booking or application back into your system. - A status page where a customer checks an order with a reference number. - Ordinary informational pages around any of the above. ## Before you publish - Check every public request: does it return more than a stranger should see? - Rate and size matter — a public request is reachable by anyone. - Keep customer-identifying data behind a reference the visitor must already know. - Use [Safe Mode](/help/app-builder-safe-mode) while testing if a page misbehaves. ## What it takes | You want | You need | |---|---| | A public page | A [Pro](/help/pro-apps) app with a page set to Public | | Live data on that page | A public [web request](/help/pro-apps-requests) with stored credentials | | A custom address | Not yet available — public apps use their Operator address today | ## Playbooks that use this - [Product configurator website](/help/playbook-configurator) --- # Playbook: Price-watching agent *Supplier or competitor prices change and nobody notices until margin is gone* ## The problem Purchase prices drift. A supplier raises a price list, a competitor drops a price, an exchange rate moves — and you find out weeks later, in the margin report. Checking manually is boring work nobody does consistently. ## What you end up with An agent that wakes up on its own every morning, compares today's prices with what it saw last time, and sends you only the differences: what changed, by how much, and which of your products it affects. Nothing changed means no message. ## What it needs - **Access level:** Power User or above (scheduled activation). - **Instance:** a connected ERP.net instance, if you are watching your own purchase prices or product costs. - **Pro app:** not required for the agent. Required only if you also want a screen showing price history. - **Outside sources:** if you watch competitor prices on the web, the agent uses web search — no extra setup. ## Build it step by step 1. Open a new conversation with the **Agent Builder**. 2. Describe the agent: > Create an agent called "Price Watch". Every working day at 07:00 it > should read the current purchase prices for the products in the > "A-class" group from my instance, compare them with the prices it > reported last time, and notify me only about products whose price > changed by more than 1%. The message should list product, old price, new > price, percentage and supplier, sorted by the largest change. 3. When the Builder asks how it should remember the previous prices, choose the simplest option that fits: either it reads the previous price from the instance, or — if you want a real history — say: > Keep a history of the prices you report so you can compare against the > last run. 4. Open the **Activation** tab of the agent and confirm the schedule is there and enabled. 5. Set how you want to be told: a notification in Operator, an email, or both. > Send the summary to me by email as well, with subject "Price changes — > ". 6. Save. ## Try it Don't wait until tomorrow morning. In chat, tell the agent: > Run your daily price check now and show me what you would send. Read the output as if it arrived at 07:00. Too noisy? Raise the threshold. Too quiet? Lower it or widen the product group. ## Variations - **Competitor watch** — point it at public web pages instead of your instance: *"check these three competitor pages every Monday and report price changes for the products I listed."* - **Cost-to-price guard** — have it compare purchase price against your sales price and flag anything where the margin fell below a limit. - **Currency-sensitive** — ask it to include the currency and flag changes that are purely exchange-rate driven. - **With a screen** — pair it with a small [Pro app](/help/pro-apps) that stores each run in a table and charts the history. ## Where it can go wrong - **A flood on day one.** The first run has nothing to compare against. Tell it to treat the first run as a baseline and stay quiet. - **Too many products.** Watching tens of thousands of items in one run is slow and expensive. Scope it to the products that matter, or split it by group across weekdays. - **Silence is ambiguous.** If you want reassurance, ask for a short "nothing changed" message rather than no message at all. - **Permissions.** If the agent can't see purchase prices, check the [permission policies](/help/permission-policies) for its instance. --- # Playbook: Email answering agent *The same customer questions arrive fifty times a week* ## The problem "Where is my order?" "Do you have this in stock?" "Can you resend the invoice?" Each one is two minutes of someone's attention, and there are hundreds of them. Meanwhile the genuinely difficult emails wait in the same queue. ## What you end up with An agent that follows a mailbox. When mail arrives it reads it, finds the answer in your data and documentation, and either replies directly or prepares a draft for a person to approve. Anything it should not answer alone — a complaint, a price negotiation, anything legal — it hands over with a short summary instead of guessing. ## What it needs - **Access level:** Power User or above. - **Instance:** connected, if answers depend on orders, stock or invoices. - **Mailbox:** a Microsoft 365 or Gmail mailbox connected to the agent. - **Pro app:** not required. ## Build it step by step 1. Open the **Agent Builder** and describe the job: > Create an agent called "Inbox Assistant". It should follow my support > mailbox. For each incoming email it decides whether it can answer from > our documentation and from the customer's data in the instance. If yes, > it prepares a reply in the customer's language. If the email is a > complaint, a pricing negotiation, or anything about contracts, it must > not answer — it should notify me with a two-sentence summary instead. 2. When the Builder offers to set up the mailbox, accept and sign in to the mailbox you want followed. This creates the activation trigger for you. 3. Decide how bold it should be. Start cautious: > For the first two weeks, never send directly. Always prepare a draft and > tell me it is waiting. 4. Give it the tone and boundaries you'd give a new colleague: > Always be brief and polite. Never promise a delivery date that is not in > the order. Never quote a price that is not in the system. Always sign as > "Customer Care". 5. Save, then open the **Activation** tab and confirm the mailbox trigger is enabled. ## Try it Send a test email to the mailbox from another address — something ordinary like *"could you tell me the status of order 10432?"* Within a minute you should see a run in the agent's **Executions** tab, and a draft or a notification. Open the run to see exactly what it looked up. ## Variations - **Triage only** — no answers at all: it just labels and routes each email to the right person. - **Internal mailbox** — the same pattern on an internal address for IT or HR requests. - **Multilingual** — it replies in whatever language the customer wrote in; say so explicitly in the instructions. - **Escalation with a ticket** — have it create a support ticket for anything it hands over, so nothing is lost. ## Where it can go wrong - **Over-confidence.** Agents that are told to "be helpful" invent answers. Tell it explicitly what it must never state without a source. - **Reply-all storms.** Be specific about who a reply goes to. - **Loops.** Exclude automated senders, bounce messages and your own outgoing addresses, or two robots will talk to each other all night. - **AI disclosure.** Every email an agent sends identifies itself as AI — this is not optional. See [AI Disclosure in Email](/help/ai-email-disclosure). --- # Playbook: Product configurator website *Customers phone to ask "can I get it in this size, this colour, what does it cost?"* ## The problem Configurable products — windows, furniture, machines, packages — generate endless pre-sales questions. Each one costs a salesperson a phone call and the customer a wait, and half of them never become an order. ## What you end up with A public web page where the customer chooses the options themselves, sees the price update as they choose, and sends the configuration as an enquiry that lands in your system. No login, no account, works on a phone. ## What it needs - **Access level:** App Builder access. - **Pro app:** yes — public pages and web requests are Pro features. - **Instance:** connected, if prices and options come from your product data. - **Public request:** one server-side request that supplies options and prices to anonymous visitors. ## Build it step by step 1. In the **App Builder**, start a new app: > Build a Pro app called "Configurator". The home page must be public — no > login. A visitor chooses a product family, then size, colour and > accessories, and sees the total price update immediately. At the end they > enter their name, email and phone and send the configuration as an > enquiry. 2. Let the Builder set up the data path. Say where the numbers come from: > Take the available options and prices from our product data. Create a > public web request for it — the page must not read the instance > directly. The Builder creates the request, and if it needs a credential it will ask you for exactly one value and open the form so you only paste it. 3. Decide what an enquiry becomes: > When a visitor sends a configuration, store it and email it to > sales@example.com with all the chosen options and the calculated price. If you want it in ERP instead, say so: *"create an enquiry record in the instance"* — that runs server-side through the same request mechanism. 4. Make it look like you: > Use our brand colours, put the logo top-left, and make it work well on a > phone. 5. Publish and copy the public address from the maximize button. ## Try it Open the public address in a private browser window — no Operator session. Configure a product, check the price, send an enquiry, and confirm it arrives. That private window is the only honest test: in your normal browser you are logged in and everything works even when it shouldn't. ## Variations - **Quote instead of enquiry** — generate a PDF quotation the visitor can download. - **Availability** — show a simple in-stock / made-to-order indicator rather than exact quantities. - **Dealer version** — a second, non-public page with dealer pricing, open only to signed-in users. - **Embedded** — put the page in an iframe on your existing website. ## Where it can go wrong - **Exposing too much.** The public request decides what leaves your system. Return the price for the chosen combination, not the whole price list. - **Stale prices.** Decide whether the page reads live prices or a published list, and say which on the page. - **Spam.** An open form will be found by bots. Ask the Builder for a simple guard and keep enquiry emails filterable. - **"It asks me to log in."** The page's access mode is not public, or you are testing a non-public page — see [Pages](/help/pro-apps-pages). --- # Playbook: Mobile sales app *Salespeople on the road can't see stock, prices or customer history* ## The problem A salesperson standing in a customer's shop needs three things: what this customer bought before, what it costs them, and whether it's available. The desktop ERP is not an option on a phone in a doorway, so they phone the office instead — or promise something wrong. ## What you end up with A phone-sized app they install on their home screen. It opens on their customers, shows history and prices for the one they pick, and lets them capture an order or a visit note on the spot. ## What it needs - **Access level:** App Builder access. - **Instance:** connected — the app reads live customer, price and stock data. - **Pro app:** only if you want the app to keep its own data, like visit notes or draft orders that are not yet ERP documents. - **Sharing:** each salesperson needs the app shared with them, or access via the instance. ## Build it step by step 1. In the **App Builder**: > Build an app called "Sales on the Road", designed for a phone. It opens > with a searchable list of my customers. Tapping a customer shows their > last ten orders, their agreed prices, and their outstanding balance. 2. Add the capture step: > From a customer, the salesperson can start a new order: search products, > set quantity, see the customer's price and the current stock, and send > the order to ERP. 3. Add the small things that make it usable outdoors: > Big tap targets, one column, works with one thumb. Keep the search box > always visible. Show the stock as a coloured indicator, not a number. 4. If you want visit notes, make it Pro and say: > Store visit notes in the app's own table, one row per visit, with the > customer, date, note and the salesperson's name. 5. Share it with the sales team — see [Sharing Apps](/help/app-sharing) — and tell them to open it and use **Add to home screen**. ## Try it Open the app on an actual phone, not a resized browser window. Walk through one real customer: find them, read their history, build a small order, send it, and confirm the document in ERP. Anything that needs two hands or a pinch to zoom goes back to the Builder. ## Variations - **Read-only version** for people who should see but not order. - **Route for today** — start on the visits planned for today rather than the full customer list. - **Photo capture** — attach a shelf photo to the visit note. - **Voice** — combine with the [voice sales executive](/help/playbook-voice-sales) for hands-free work in the car. ## Where it can go wrong - **Too much on one screen.** Desktop layouts fail on phones. Say "phone first" in every correction. - **Slow lists.** Thousands of customers in one list is slow. Ask for search and paging rather than everything at once. - **Wrong prices.** Make sure the app asks for the price *for this customer*, not the list price. - **Connectivity.** Coverage in a basement is nobody's friend. Keep the flow short so a lost connection costs one screen, not an hour. --- # Playbook: Voice sales executive *A salesperson is driving and can't type an order or a visit report* ## The problem The best moment to record what happened at a customer is the minute after leaving. That is exactly the moment the salesperson is in a car with both hands on the wheel. By the evening, half the detail is gone. ## What you end up with An agent they talk to. They say what happened; it asks the one or two questions it needs, writes the visit up properly, and — if they dictated an order — creates it and reads back the total for confirmation before saving. ## What it needs - **Access level:** Power User or above to create the agent. - **Instance:** connected, for customers, prices and orders. - **Speech:** microphone access in the browser. See [Speech Setup](/help/speech-setup). - **Phone number:** optional — an agent can also answer on a real phone line, see [Phone Numbers](/help/phone-numbers). ## Build it step by step 1. Open the **Agent Builder**: > Create an agent called "Sales Voice". It is used hands-free by > salespeople after a customer visit. It should accept a spoken summary, > identify the customer, write a clean visit report, and store it. 2. Add the order path: > If the salesperson dictates an order, find the products they name, use > that customer's prices, then read back the products, quantities and total > and wait for a spoken confirmation before creating the order. 3. Tune it for speaking rather than reading: > Keep every answer under three sentences. Never read out long lists — ask > a narrowing question instead. Always confirm names and quantities you > were unsure about. 4. Set the reasoning level to a fast one so the conversation doesn't lag. 5. Share it with the sales team and tell them to tap the microphone in chat, or dial the agent's number if you assigned one. ## Try it Speak a realistic sentence with a mumble in it: *"visited Petrov today, they want twenty of the six-millimetre and maybe some of the eight."* A good agent asks which eight-millimetre item and how many — it doesn't invent an answer. ## Variations - **Phone line** — give it a number and let people call it, including from a car's handsfree. - **Report only** — no ordering, just a well-written visit report filed against the customer. - **Daily debrief** — combine with a schedule so it phones or messages at 18:00 asking how the day went. - **Multilingual** — it can work in whichever language the salesperson speaks. ## Where it can go wrong - **Product names in speech.** Codes and dimensions are misheard constantly. Tell the agent to always confirm the product it matched. - **Silent order creation.** Never let it create a document without a spoken confirmation. - **Long answers.** A voice agent that reads a table out loud is unusable. Cap the answer length in the instructions. - **Noise.** In a moving car, expect retries. Short exchanges survive; long ones don't. --- # Playbook: Overdue invoice chaser *Overdue invoices pile up because nobody has time to chase them* ## The problem Chasing money is unpleasant, repetitive and always last on the list. Invoices drift past due, the reminder goes out three weeks late — if at all — and the conversation with the customer is harder than it needed to be. ## What you end up with An agent that reviews open receivables every morning, decides which ones are due a reminder and which tone that reminder deserves, drafts the messages, and records what it sent so the next reminder escalates properly. ## What it needs - **Access level:** Power User or above. - **Instance:** connected — open invoices, due dates and payments live there. - **Mailbox:** a mailbox for sending, if you want it to send rather than draft. - **Pro app:** not required. ## Build it step by step 1. In the **Agent Builder**: > Create an agent called "Receivables". Every working day at 08:00 it > reviews unpaid customer invoices past their due date. 2. Define the escalation ladder explicitly — this is the part that matters: > Use three stages. 1–14 days overdue: a friendly reminder. 15–30 days: a > firmer reminder that mentions the amount and the due date. Over 30 days: > do not write to the customer — notify the account manager and me > instead. 3. Say what must never happen: > Never contact a customer twice within seven days. Never chase an invoice > that is disputed or on a payment plan. Never state a payment deadline > that is not in the invoice. 4. Start in draft mode: > For now, prepare the emails and show them to me for approval rather than > sending them. 5. Add the record-keeping: > Keep a note on each invoice of what you sent and when, so the next > reminder knows which stage it is at. 6. Enable the schedule in the **Activation** tab. ## Try it Ask it in chat: > Show me what you would send today, grouped by stage, with the customer, the > invoice, the amount and the days overdue. Read the stage-three list first. If somebody you know is on it who shouldn't be, that is a rule to add before you let it send anything. ## Variations - **Statement instead of per-invoice** — one message per customer listing all their overdue documents. - **Pre-due courtesy** — a gentle note three days *before* the due date; it prevents more late payments than any reminder after. - **Collections handover** — anything past a limit becomes a task or a ticket for a person. - **With a screen** — a [Pro app](/help/pro-apps) showing the ageing list and what was sent to whom. ## Where it can go wrong - **Chasing paid invoices.** Make sure it reads payments and credit notes, not just the invoice. Nothing damages a customer relationship faster. - **Wrong recipient.** Send to the accounts contact, not the person who once placed an order. - **Tone.** Read the stage-two wording yourself before enabling sending. - **AI disclosure.** These emails identify themselves as AI-sent — see [AI Disclosure in Email](/help/ai-email-disclosure). Decide whether the account manager should be the sender for sensitive accounts. --- # Playbook: Approvals desk *Approval requests get lost in email threads* ## The problem Purchase requests, discounts, days off, expense claims — they travel by email, get forwarded, sit in someone's inbox while they're away, and nobody can say what is waiting on whom. The person approving wants one screen; the person waiting wants an answer. ## What you end up with An internal app with two views. Requesters see their own requests and the status of each. Approvers see everything waiting for them, with the context they need to decide, and approve or reject with one tap and an optional comment. ## What it needs - **Access level:** App Builder access. - **Instance:** connected, if the requests relate to ERP documents or if you want approvals written back. - **Pro app:** yes, if requests live in the app itself rather than in ERP — they need [table storage](/help/pro-apps-tables). - **Sharing:** the app shared with requesters and approvers. ## Build it step by step 1. In the **App Builder**: > Build a Pro app called "Approvals". It has two views. As a requester I > see my own requests and their status. As an approver I see everything > waiting for my decision. 2. Describe one request type properly before adding more: > Start with purchase requests. A request has a title, a supplier, an > amount, a currency, a reason, and an optional attachment. Store requests > in the app's own table. 3. Define who approves what: > Anything up to 1000 is approved by the team lead. Above that it also > needs the finance manager. Show the approver only what is theirs to > decide. 4. Make deciding fast: > Approve and Reject buttons on the row itself. Rejecting requires a > comment. Show the requester's previous requests so the approver has > context. 5. Close the loop: > Notify the requester as soon as a decision is made, and notify the > approver when something new is waiting. 6. Share it with the team. ## Try it Log in as yourself and raise a request, then have a colleague open their view. The question to answer is: could they decide without asking you anything? If they'd need to ask "what is this for?", add that field. ## Variations - **Days off** — same structure, different fields, plus a calendar view. - **Discount approval** — pulled from the order the salesperson is working on. - **Write back to ERP** — the approval changes a document state rather than only a row in the app. - **Agent assist** — an agent pre-checks each request against your rules and adds a recommendation before a human decides. ## Where it can go wrong - **Silent queues.** Without notifications it becomes another place nobody looks. Notify on both sides. - **Absent approvers.** Decide up front what happens when someone is on holiday — a deputy, or escalation after N days. - **Everything at once.** One request type, working well, beats five half-finished ones. - **Audit.** Keep the decision, the comment, the person and the timestamp. You will be asked about it eventually. --- # Playbook: Field service check-in app *Field technicians report time and materials on paper* ## The problem A technician finishes a job, writes hours and parts on a sheet, and it reaches the office days later — smudged, incomplete, and impossible to invoice accurately. Nobody knows where anybody is until they call. ## What you end up with A phone app the technician opens on site. They pick their job, check in, record the time spent and the materials used, photograph the result, and check out. The office sees it immediately and can invoice from it. ## What it needs - **Access level:** App Builder access. - **Instance:** connected — jobs, customers and materials come from there, and reported work goes back. - **Pro app:** yes, if you want photos and offline-ish drafts stored with the app — that uses [file storage](/help/pro-apps-files) and [table storage](/help/pro-apps-tables). - **Sharing:** the app shared with the field team. ## Build it step by step 1. In the **App Builder**: > Build a Pro app called "Field Service", phone first. It opens on today's > jobs assigned to the signed-in technician, nearest first, each showing > the customer, address, contact phone and what needs doing. 2. Add the on-site flow: > From a job the technician taps Check in, which records the time. They can > then add hours, add materials from our product list with quantities, and > write a short work description. Check out records the end time. 3. Add evidence: > Allow up to three photos per job, stored with the job. 4. Send the result home: > When the technician checks out, write the reported hours and materials > back to the job in ERP and notify dispatch. 5. Handle the practicalities: > Make the address tappable so it opens the map, and the phone number > tappable to call. 6. Share it with the team; they install it to the home screen. ## Try it Give it to one technician for one day before rolling it out. Then ask them a single question: what did you still write on paper? Whatever they answer is the next thing to build. ## Variations - **Signature** — capture the customer's signature on the phone at check-out. - **Checklists** — a required list of steps per job type, so nothing is skipped. - **Parts from van stock** — deduct materials from the technician's own stock location. - **Dispatch view** — a second, desk-sized app showing where everyone is. ## Where it can go wrong - **Poor coverage.** Basements and plant rooms have no signal. Keep each step small and saveable so a lost connection costs one field, not the visit. - **Material search.** Technicians will not scroll a catalogue. Give them recent items and a fast search, or a scan. - **Photo size.** Full-resolution photos are large; ask for them to be resized before storing, and watch the app's storage limits. - **Double reporting.** If the office also keys the sheet in, you get both. Switch the paper off on the same day. --- # Playbook: Management cockpit *Management asks for numbers that take a day to assemble* ## The problem Every Monday somebody exports three reports, pastes them into a spreadsheet, fixes the same two columns, and emails a picture of the business that is already a week old. When a follow-up question comes back — *why is the south region down?* — the whole exercise starts again. ## What you end up with One screen with the numbers that matter, calculated on live data, plus a question box: anyone looking at it can ask *"why is the south region down?"* and get an answer from the same data, in the same place. ## What it needs - **Access level:** App Builder access. - **Instance:** connected — this is entirely about live data. - **Pro app:** optional; only needed if you want to store targets, or keep a history of snapshots. - **Sharing:** shared with the management team, read-only is fine. ## Build it step by step 1. Decide the numbers before you open the Builder. Five or six, each with an owner who cares about it. A cockpit with twenty tiles is a wallpaper. 2. In the **App Builder**: > Build an app called "Cockpit" for management. Show six figures for the > current month with the same period last year next to each: revenue, > gross margin, new customers, open orders value, overdue receivables, and > stock value. 3. Add movement, not just level: > Under each figure show the trend for the last twelve months as a small > chart. Colour improvement and deterioration differently. 4. Add the breakdown people always ask for next: > Tapping revenue breaks it down by region, then by salesperson, then by > customer. 5. Add the question box — see [AI in Apps](/help/app-builder-ai): > Add a box where a user can ask a question in plain language about the > figures on screen, answered from the same live data. 6. Make it refresh sensibly: > Refresh when the page is opened and when the user asks, not constantly. 7. Share it read-only with the management team. ## Try it Open it on Monday morning instead of building the spreadsheet, and ask it the first question that comes to mind. If the answer takes longer than the export would have, the underlying query needs narrowing — tell the Builder which figure is slow. ## Variations - **Targets** — store monthly targets in a [table](/help/pro-apps-tables) and show attainment rather than raw numbers. - **Daily digest** — pair it with an agent that messages the same figures at 07:00, so nobody has to open anything. - **Per-role cockpits** — a sales one, a warehouse one, a finance one; each short. - **TV mode** — a large-format page for a wall screen. ## Where it can go wrong - **Heavy queries.** Summaries are computed on the server across all matching records — good — but asking for a year of detail row by row is slow. Ask for totals, not lists. - **Definitions.** "Revenue" means three different things in most companies. Write the definition on the screen. - **Permissions.** Not everyone should see margin. Consider two versions rather than one with hidden rows. - **Tile creep.** Every new tile makes the others less visible. Remove one before adding one. --- # Working with the UI Operator's interface is built around a few persistent controls that tell the AI **who you are talking to** (the agent), **which ERP.net instance** you are working with, and **which conversation** you are in. Once you know how those three pieces behave, the rest of the app falls into place. ## The top bar From left to right: - **Agent selector** — picks the agent (or app / site) that will handle your next message. See [Agent Selector](ui-agent-selector). - **Reasoning / model controls** — choose the reasoning level for the next message (for example, high or low). - **History** — opens the conversation list in a right-hand sidebar. See [Conversations & History](ui-conversations). - **Notifications** — the bell shows an unread badge when background runs finish, executions fail, or someone shares an agent or app with you. See [Notifications](notifications). - **Instance selector** — picks the ERP.net instance connection your messages run against. See [Instance Selector](ui-instance-selector). - **User menu** — settings, theme, sign-out. ## Conversation history Operator keeps your past conversations in the right-hand sidebar that slides out from the **History** button. The **New** button (also in the top bar) starts a fresh chat using your *tab defaults* (the agent and instance you picked last). Old conversations are read-only with respect to the selectors — opening one shows what was used at the time, but does not change your defaults. See [Conversations & History](ui-conversations). ## The chat area The main panel shows the active conversation: messages, tool calls, attachments, and the composer at the bottom. The composer carries a few inline controls (attachments, voice, reasoning level) that apply to the **next** message you send. Open its **+** menu and choose **Appearance** to switch between Light, Dark, and System themes. This is also available when Operator is embedded and the top bar is hidden. ## Settings and connections - **Settings** (user menu) — appearance, language, notifications, default reasoning, and other preferences. - **My Connections** — manage every ERP.net instance you can talk to. Covered in [Instance Connections](instance-connections). ## Where to go next - [Agent Selector](ui-agent-selector) — how agents are picked and remembered across tabs. - [Instance Selector](ui-instance-selector) — same persistence model, applied to ERP.net connections. - [Conversations & History](ui-conversations) — the New button, opening old chats, properties, search. - [Instance Connections](instance-connections) — the connections behind the instance selector. --- # Agent Selector The **agent selector** in the top bar is your main navigation for agents and their workspaces. Choosing an agent starts a fresh chat; choosing an app, site, or builder opens that workspace. ## What you see - The current agent's icon and name. - A dropdown listing built-in agents, your custom agents, agents shared with you, and the App / Site Builder entry points. - A small badge when the selected agent has an associated user-agent (your customised version). ## Running vs. designing a custom agent Picking one of your custom agents from the dropdown **runs** it — you stay on Home (`/`) with the agent selected in Execute mode, ready to chat. If you own the agent, a small tab bar appears above the chat with **Execute / Design / Properties / …**; clicking any tab other than Execute switches into Design mode and the URL becomes `/agent/:id` (bookmarkable, reload-safe). Pressing Execute again brings you back to Home. ## How the selection is remembered Operator keeps a single **tab selection** that covers the agent, the reasoning level, and the active instance — they all share the same persistence model. - **Per browser tab** — each tab has its own selection (saved in session storage). You can have one tab on the Sales Agent and another on the Support Agent at the same time. - **Per profile** — your profile stores a default selection in the database. A brand-new tab opens on whatever you last picked anywhere. - **First load of a new tab** — Operator reads the profile default and writes it into the tab's session storage. From then on, the tab follows its own selection. ## Header navigation and conversation changes The two agent menus have deliberately different jobs: 1. **Top-bar agent selector** — always navigates. From an existing conversation, choosing another agent starts a fresh chat and leaves the old conversation assigned to its original agent. Choosing an app, site, or builder opens its workspace. 2. **Message-box + menu → Agent** — changes the agent for the conversation you are currently viewing. Use this only when you intentionally want the next message in that conversation handled by someone else. Example: while viewing a conversation with Business Specialist, choosing Advisor from the top bar starts a new Advisor chat. Choosing Advisor from **+ → Agent** keeps the same conversation and changes its assigned agent. ## Reading an old conversation Opening a conversation from the history sidebar on the right shows the agent that was used at the time. The top-bar selector can take you to a new chat or another workspace without changing that saved conversation. ## Related - [Instance Selector](ui-instance-selector) — the same persistence model, applied to ERP.net connections. - [Using Agents](agents-using) — choosing the right agent for the job. - [Creating Agents](agents-creating) — building your own. --- # Instance Selector The **instance selector** in the top bar picks which ERP.net connection your messages, tools, and apps run against. Unlike the [Agent Selector](ui-agent-selector), it cannot change an existing conversation. ## What you see - The active connection's display name. - A coloured status dot — Active (green), Expired (gray), or Disconnected (muted). See [Instance Connections › Status indicators](instance-connections#status-indicators). - A 🏠 badge if the connection is your home connection. - A dropdown with all your connections, an **Add new** entry, and a **Buy AI Credits** entry on instances you administer. ## How the selection is remembered The instance selection is part of the same tab selection that holds your agent and reasoning level: - **Per browser tab** — each tab can be pointed at a different instance. - **Per profile** — your profile stores a default. A new tab opens on whatever you last picked. - **First load of a new tab** — Operator reads the profile default into the tab's session storage on first mount. ## When the picker writes to the profile - **Fresh-start change** — switching instance from the Home screen (or pressing **New** and then switching) updates both the tab and the profile default. New tabs will inherit it. - **In-conversation change** — not allowed. Inside an existing conversation the instance selector is **read-only** and shows the connection that conversation was bound to. Pressing **New** returns you to your tab's instance. This guarantees that browsing an old conversation against a different instance never silently rewires your defaults. ## OAuth, reconnects, token refresh When a connection expires or you go through the ERP.net sign-in flow again, the result is written only to the **current tab** — not to your profile. Your home instance and your default selection are preserved. ## Adding and managing connections The dropdown's **Add new** entry opens the same dialog as the My Connections page. For everything else — renaming, setting the home connection, AI credit budgets, deleting — see [Instance Connections](instance-connections). ## Related - [Instance Connections](instance-connections) — the connections behind the selector; adding, editing, removing. - [AI Credit Budget per Connection](instance-connections#ai-credit-budget-per-connection) — per-instance billing. - [Agent Selector](ui-agent-selector) — same persistence model for agents. --- # Conversations & History Your past conversations live in a **right-hand sidebar**. Click the **History** button in the top bar to slide it out — you'll see your recent chats, a search box, and per-row actions. The **New** button — also in the top bar — starts a fresh chat. This page covers what each control does and how it interacts with the agent and instance selectors. ## The "New" button **New** clears the chat area and starts a fresh conversation using your **tab defaults**: - the agent currently in the [Agent Selector](ui-agent-selector), - the instance currently in the [Instance Selector](ui-instance-selector), - your tab's reasoning level. It does **not** ask the server for anything until you send your first message — so pressing New is free. ## Opening an old conversation Open the history sidebar from the **History** button in the top bar and click a conversation to load it into the chat area. While it is open: - The top-bar agent selector shows the conversation's agent. Choosing another item there starts a new chat or opens its workspace; it does not reassign the open conversation. - To intentionally change the agent for the open conversation, use **+ → Agent** in the message box. - The instance selector is **read-only** and shows the connection bound to the conversation. - Pressing **New** snaps both selectors back to your tab defaults. ## The conversation menu Each row in the history sidebar has a `⋯` menu (also available via right-click): - **Properties** — opens a dialog with the conversation's full metadata: title, ID, status, type, created / updated timestamps, agent (key + name), instance connection ID, reasoning level, app / site IDs. - **Rename** — change the title. - **Delete** — soft-deletes the conversation. It disappears from the list but can be restored by support if needed. ## Queue your next message You don't have to wait for an answer to finish. While the agent is working, type your next message and press Enter (or the clock button next to Stop) — it is **added to the queue** instead of interrupting. - Queued messages appear as small cards just above the message box, in the order they will run. - Each card has **Edit** (change the wording before it runs) and **Remove**. - When the current answer finishes, the first queued message is sent automatically and the answer streams as usual. - The queue is kept for you, not just for this browser tab: reload the page, or come back on another device, and your queued messages are still there and still run. - If another browser tab tries to start an answer for the same conversation at the same moment, that extra attempt is refused instead of running alongside the first answer. Example: you ask *"Analyse last month's sales by region"*, then immediately queue *"Now compare it with the same month last year"* and *"Summarise both in three bullets"*. All three run one after the other, in order. ### Putting the queue on hold Pressing **Stop** stops the current answer **and** holds the queue, so nothing queued starts on its own. The cards stay in place and a small bar appears: **Queue on hold — Resume**. - Press **Resume** to continue from the first queued message. - Sending a new message yourself also clears the hold. - While on hold you can still edit or remove anything in the queue. ## The Apps filter The **Apps** filter in the history sidebar shows two kinds of conversations: - **App Builder chats that haven't created an app yet.** Once the app exists, its builder chat is opened from the app itself, not from History. - **AI runs started by your apps** from the last 7 days. For example, when an app button like *"Analyse with AI"* sends a file to the AI, that run shows up here right away. A green dot on the History button means it is still running. Open it to see what the app sent, which tools ran and what the AI answered, or why it failed. AI runs started by apps are visible to Power users and above, either on the platform or in the instance you have selected. They are removed automatically after 7 days. ## Search The search box at the top of the history sidebar filters by title and message content. Results highlight the matching snippet. ## Related - [Agent Selector](ui-agent-selector) - [Instance Selector](ui-instance-selector) - [Working with the UI](ui-overview) --- # Instance Connections An **instance connection** links your Operator account to a specific ERP.net instance (identified by its base URL, e.g. `https://demodb.my.erp.net`). Every chat, app, automation and search runs against a single active connection at a time. You can have as many connections as you need — one per instance you work with, or even multiple connections to the same instance (for example, one as an Internal User and one as a Client). ## Connection types - **Internal User** — you log in interactively with your own ERP.net account through the standard sign-in screen. Use this for instances where you have your own user (employees, partners, internal users). - **Client** — the instance is contacted via stored client credentials configured in the instance. Use this when you don't have a personal user but the instance owner has granted you a client identity (typically external customers). Internal connections support OAuth refresh, so you stay signed in across sessions until the refresh token expires. Client connections re-authenticate transparently from the stored credentials. ## Where you manage connections There are two places in the UI: ### Instance selector (top bar) The dropdown in the top bar shows all your connections, with the active one ticked. From here you can: - **Switch the active connection** — pick any connection in the list. The whole app reloads its context (entity schemas, agents, tools, capabilities) for the new instance. - **Add a new connection** — opens the same dialog as on the My Connections page. - **Buy AI Credits** — only shown when the active instance is one you administer. Routes to `/billing-credits`. - **See connection status** — a coloured dot on each entry indicates Active / Expired / Disconnected. ### My Connections page Open it from the user menu or directly at `/my-instance-connections`. This is the full management surface — name, type, home flag, AI credit budget, status, enterprise/client context, plus connect / reconnect / disconnect actions. The rest of this page describes what you can do there. ## Adding a connection Click **Add New** in the top right. In the dialog: 1. **Instance URL** — type the instance subdomain (e.g. `demodb`); Operator wraps it as `https://.my.erp.net`. 2. **Display Name** — how the connection appears in the selector. Auto-generated from the instance name; override freely. 3. **Connect as** — choose **Internal User** (you sign in with your own ERP.net account) or **Client** (stored client credentials). See [Connection types](#connection-types). 4. **Set as my home connection** — only offered for the very first internal connection (when you don't have a home yet). Click **Add Instance**. For Internal connections, the next time you select the connection you'll be taken through the ERP.net sign-in flow; the resulting tokens are stored against the connection. ## Editing a connection Use the row's `⋯` menu → **Edit**. You can rename it and adjust connection-type-specific fields. For an existing non-home internal connection you'll also see the **AI credit budget** picker — see [AI credit budget per connection](#ai-credit-budget-per-connection). ## The home connection Exactly one of your connections is marked as your **home connection** (shown with a 🏠 badge). The home connection is your default billing target for AI usage when you haven't overridden it on a per-connection basis. The first internal connection you add is automatically set as home. To change it later, open the row's `⋯` menu and pick **Set as home** — the previous home loses the badge. ## AI credit budget per connection Each connection pays for its AI usage from one of two budgets: - **Home connection** (default) — credits come from your home connection's instance pool. - **This instance** — credits come from a per-instance budget that the instance admin allocated specifically to you on this instance. You change this in **My Connections → Edit Instance**, under *AI credit budget*. The dialog shows the current balance for both options. **When "This instance" is selectable** — only once an instance admin on that instance has topped you up there. Until then the option is disabled with the hint *"ask the instance admin to top you up"*. See [Managing User Budgets](billing-user-budgets) for the admin-side view. **No silent fallback** — if you choose **This instance** and that budget runs out, AI calls on that connection will **fail with an explicit error**. They will not silently fall back to your home pool. This is intentional — it lets the party that funds the budget control spend on that connection. **When this matters** — the classic scenario is an external consultant connecting to a customer's instance. By default the consultant's AI usage on that connection bills their own home pool. Once the customer's instance admin allocates AI credits to the consultant on that instance, the consultant can switch the connection to **This instance** and from then on usage is billed to the customer-funded budget. If that budget is exhausted, the consultant gets an error rather than silently consuming their own credits. See also: [Buying AI Credits](billing-credits) and [Managing User Budgets](billing-user-budgets). ## Connecting, reconnecting, disconnecting The `⋯` menu adapts to the current status: - **Connect** — appears when the connection has no valid access token. Loads tokens from storage if possible, otherwise opens the ERP.net sign-in flow. - **Reconnect** — for an active connection, forces a fresh sign-in (useful after permission changes on the instance). - **Disconnect** — clears the in-memory tokens for the active connection. The connection row itself stays; tokens stay encrypted in storage and can be reused via Connect. ## Setting the enterprise / client context Once a connection is active, the `⋯` menu shows either **Set Enterprise Context** (internal connections) or **Set Client Context** (client connections). This pins which company / location / customer is implied in subsequent AI requests, so you don't have to spell it out every time. ## Removing a connection `⋯` → **Delete** removes the connection record and any stored tokens. The instance itself isn't affected — you can re-add it later. You can't delete the only remaining connection that's currently set as home unless another one becomes home first. ## Status indicators Each connection has one of three statuses, shown in both the top-bar dropdown and the My Connections table: - **Active** (green) — there's a valid access token; the instance is reachable. - **Expired** (gray) — the access token expired but a refresh token is still on file (or the connection is a Client connection that can re-authenticate). One click on **Connect** or **Reconnect** restores it. - **Disconnected** (muted) — no usable tokens. You'll be sent through the sign-in flow next time you select the connection. Hovering the badge shows exact expiry timestamps for both the access and refresh tokens. ## Troubleshooting If a connection refuses to come up: - Check that **Operator** is installed in the instance (you'll see a banner if it isn't). - For Client connections, verify the client credentials configured on the instance side haven't been rotated. - Try **Reconnect** to force a fresh sign-in. ## Related - [ERP.net Integration overview](/help/erpnet-overview) - [Security, Identity, and Permissions](/help/erpnet-security) --- # Your Profile *Your account, AI credit budgets, and quick access to related settings.* Open the profile page from the **user menu** in the top bar — click the large card at the top of the dropdown that shows your name, email, and current credit balance. The page is organized as a main column with an **Account** card and an **AI credits** card, plus a set of **Quick links** on the right. ## Account Shows who you are signed in as: - **Avatar, display name, and email** from your identity provider. - **Role** — your platform role (Normal, Power, Partner, Employee, Admin, Developer, Owner) and the numeric level. The role controls which features are available across Operator. - **Member since** — the date your account was created. ## AI credits Every AI action in Operator is paid for from an **AI credit budget**. This card shows all your budgets and activity from the last 30 days across three tabs. ### Budgets One row per instance you have a budget on, including your **Home** instance (highlighted with a Home badge) — even when its balance is zero. Each row shows: - **Instance name and address**, and your **role** on that instance. - **Auto top-up** — either *Off*, or the *threshold → ceiling* pair. When your balance drops below the threshold, Operator automatically tops you up to the ceiling from the instance pool. - **Monthly auto limit** — how much has already been auto-topped up this month, and the cap (if set). Once the cap is reached, auto top-up pauses until the next month. Manual top-ups by an administrator are never restricted by this limit and do not count towards it. - **Last auto** — the timestamp of the most recent automatic top-up. - **Credits remaining** — your current available balance, shown large on the right. For details on how budgets are funded and administered, see [Managing User Budgets](billing-user-budgets). ### Top-ups A table of the top-ups added to your budgets in the last 30 days. Each entry shows the date, the **type** (*Manual*, *Auto*, or *Adjustment*), the **source instance** the credits came from, the credit amount, the resulting balance, and any note left by the administrator. ### Usage Your recent AI credit spend, grouped by day. Expand a day to see each conversation that consumed credits, with the **agent** that ran it, the number of messages, and the total credits used. Clicking a conversation opens it in the chat. ## Quick links Shortcuts to the pages most often reached from the profile: - **Instance connections** — manage every ERP.net instance you can talk to. See [Instance Connections](instance-connections). - **Notifications** — your notification inbox. See [Notifications](notifications). - **Sign out** — end your session. --- # Settings *Customize how Operator works for you* Open Settings by clicking the **gear icon** (⚙️) in the chat header. Settings are saved to your user profile and persist across sessions and devices. The dialog is organized into four tabs: **AI-enhanced**, **Display**, **Speech**, and **Experimental**. ## AI-enhanced These features consume a small amount of additional AI credits. | Setting | Default | What it does | |---|---|---| | **Execution details** | ON | Shows real-time status updates while the agent works — what it's searching, querying, or calling. | | **Action buttons** | ON | Lets the agent suggest interactive buttons at the end of a response: **Link buttons** (e.g. *Open in Web Client*, *View Documentation*) and **Reply buttons** (one-click replies like *Yes, proceed* or *Show only open*). | | **Topic guard** | OFF | Restricts responses to ERP.net and business topics. When on, the agent politely declines off-topic requests (weather, trivia, medical/legal/personal advice, entertainment, etc.) and redirects back to work. May be **forced on and locked** by an instance [Permission Policy](permission-policies) with *Allow off-topic conversations* turned off — typical for client or shared accounts. Topic guard is a behavioural setting, not a security boundary. | | **App Builder context depth** | empty | Limits how much of a long App Builder conversation is re-read at the start of each new request. Leave it **empty** to keep the current behaviour (the whole conversation). Enter a number from **0 to 100** to carry only that many recent exchanges (one exchange = your message plus the builder's reply). `10` is a good balance for most work; `0` means each request stands on its own. Only the *beginning* of a request is affected — once the builder is working, it keeps full continuity for that request. Shorter context means lower cost and faster starts; the builder still relies on its project memory for the bigger picture. | ## Display These features do not consume AI credits. | Setting | Default | What it does | |---|---|---| | **Actions counter** | OFF | Shows a running count of actions executed while processing a request. | | **Time elapsed** | ON | Shows how long the current request has been running. | | **Record creation links** | ON | Adds an *Open in Web Client* button for records created by the agent. Generated by the system (not the LLM), so it costs no credits. Only aggregate-root entities get a button (e.g. Sales Orders, not Sales Order Lines). If more than 4 records are created in one turn, the first 3 get individual buttons and a 4th button summarizes the rest. | ## Speech Voice conversation settings. | Setting | Default | What it does | |---|---|---| | **Speech mode** | OFF | Enables voice conversations using speech-to-speech AI. While on, a **Speech setup** button reveals controls for language, voice, speed, noise reduction, mode type, and turn detection. | ## Experimental Preview features that may change or be removed. | Setting | Default | What it does | |---|---|---| | **Tool caching** | — | Sends all tools on the first turn and omits them on follow-up turns when response chaining is active. Reduces tokens at the cost of strict ordering. | | **Prompt cache retention** | — | Keeps prompt caches alive for 24 hours so subsequent sessions reuse them. Reduces credit usage across sessions. | | **Use tools as MCP** | — | Replaces the built-in data tools (entity schema, query, update) with an MCP server reference. | | **Daisy-chain execution** *(Employee+)* | OFF | Runs long agent runs across multiple short function invocations to escape the per-invocation timeout. Each invocation runs as many turns as fit in ~240 s, then re-invokes itself for the next batch. After **15 minutes** the run pauses and you can click **Continue** to start a fresh 15-minute window; after **20 minutes** it is hard-stopped. | > **Always fresh on each new run:** Every new user message starts the agent loop with a clean slate — the previous AI response is never re-attached. Tool-call turns *within the same run* (and daisy-chain hops of the same run) still chain normally. This is now built-in and not configurable. ## Reasoning effort Each agent has a default reasoning level that balances quality and speed. **Power Users (level 30+)** can change the level for individual conversations via the reasoning badge in the chat — up to the agent's maximum. | Level | Used for | |---|---| | **Fastest / Quick** | Quick lookups and documentation answers | | **Smart** | Day-to-day data operations | | **Expert** | Complex reasoning and configuration | | **Genius** | Maximum extended thinking | | **Savant** | The deepest level, available in App Builder only — for the hardest builds; slowest and most expensive | Defaults and ceilings per built-in agent: | Agent | Default | Maximum | |---|---|---| | Advisor | Fast | Fast | | Business Specialist | Smart | Expert | | Sales Executive | Smart | Smart | | App Builder | Expert | Savant | | Site Builder | Expert | Expert | | System Architect | Expert | Expert | ## Home screen vs. loaded conversations The agent you pick on the home screen is your **default for new chats**. Loading an older conversation from history temporarily switches to that conversation's agent; returning home (logo or **New**) restores your home selection. This prevents accidental drift just from browsing past chats. --- # Notifications The bell icon in the top bar keeps you informed about things that happen while you work — agent runs that finish in the background, runs that fail, runs waiting for your confirmation, and items shared with you. ## What you'll be notified about - **Agent executions** — when a long-running agent finishes, fails, or pauses waiting for you to confirm an action. Short runs (under a few seconds) that finish while you're watching don't generate a notification. - **Sharing** — when someone shares an agent or an app with you. - **Agents** — messages an agent sends you on its own, for example when work it was doing in the background is finished or when it needs a decision from you. - **System messages** — occasional platform updates, including a monthly **"What's new"** digest on the 1st of each month that links to that month's release notes (only sent when there are new release notes to announce). ## Reading and managing notifications Click the bell to see your latest notifications. From there you can: - Click any item to open it (jumps you to the related conversation, agent, or app). - Mark items as read individually or all at once. - Dismiss items you no longer want to see. - Open the full **Notifications** page for filtering by category and reviewing older items. ## Pop-up toasts When you're using the app, new notifications also appear briefly as a pop-up in the corner. You can turn these off in the Notifications page if you prefer the quieter bell-only experience. ## Device notifications Turn on **Device notifications on this device** in the Notifications page to get alerts from your phone or computer even when Operator is closed. Tapping an alert opens the related conversation, agent or app. When you install Operator as an app on your phone or computer, you're asked once whether to turn on device notifications — tap **Turn on** and you're set. If your browser already allows notifications, they turn on by themselves the first time you open the installed app. A few things worth knowing: - The setting applies to the device you're on. Turn it on separately on your laptop and your phone. - On iPhone and iPad, add Operator to your Home Screen first — Apple only allows alerts for apps installed that way. - If your browser has blocked notifications for Operator, unblock them in the browser's site settings and switch it on again. - Muted categories stay muted: if you mute Executions, no device alerts arrive for agent runs either. ## Notifications from agents An agent you created can notify you whenever it has something worth your attention. That always works — you own it. An agent someone else created has to ask first: - The first time it tries to reach you, you get a single permission request that shows the message it wants to send, together with the agent's name and who runs it. - Choose **Allow** and the message is delivered straight away, and that agent can notify you from then on. Choose **Block** and the message is discarded and the agent can never notify you again. - If you leave the request unanswered and the agent tries again, you don't get a second request — the waiting request is updated with the newest message and moves back to the top of your list. Unanswered requests disappear after 30 days. - Any agent may send you at most 20 notifications per day. You can change your mind at any time under **Agents that can notify you** on the Notifications page. Example: a colleague's stock-watch agent finds that a product fell below its minimum level. You get one request — "Stock Watch, run by Maria Petrova, wants to send you notifications" — showing the alert itself. Allowing it delivers the alert and lets future alerts through; blocking it ends the matter. ## Muting categories If a category gets noisy, mute it from the Notifications page. Muted categories stop creating new notifications until you un-mute them. ## Retention Notifications are kept automatically for a limited time: read items for 30 days, dismissed items for 7 days, and anything older than 90 days is removed. --- # Speech Setup *Configure how Operator listens and speaks* When **Speech mode** is enabled in [Settings](/help/settings), a **Speech setup** button appears below the toggle. It opens the Speech Setup dialog, where you tune how voice input and output behave. Open it from **Settings → Speech tab → Speech setup**. ## Mode Choose how voice input and output are processed. The mode you pick affects which turn-detection options are available. | Mode | What it does | Best for | |---|---|---| | **Dictation** | Transcribes your speech into the input field. You review the text and send it manually. | Composing long messages, mail replies, careful editing | | **Voice → Text** | Voice input is transcribed and processed by the full text engine. The reply is shown as text, not spoken. | Hands-free input when you still want to read the answer | | **Voice → Text → Voice** | Voice is transcribed, processed deeply by the text engine, then read aloud. Slower but uses the full reasoning power of the text model. | Complex tasks where you also want spoken answers | | **Voice ⇄ Voice** | Direct speech-to-speech. Fast, picks up tone, supports interruptions. | Natural dialogue and quick lookups | ## When to send / when the AI responds Controls when your turn ends. The label changes with the mode — in **Dictation** it's *"When should the text be sent?"*; in the other modes it's *"When should the AI respond?"*. | Option | Behavior | Notes | |---|---|---| | **Manual (press a button)** | You decide when to send. | Not available in **Voice ⇄ Voice** | | **After a short pause — 0.5 s** | Sends quickly after you stop talking. | | | **After a pause — 0.8 s** | The default. Comfortable balance. | | | **After a longer pause — 1.1 s** | More tolerant of mid-sentence thinking. | | | **After a long pause — 1.4 s** | Most tolerant. | | | **Automatically (semantic)** | The system detects when you've finished a thought. | Only in **Voice ⇄ Voice** | If you switch modes and your current choice isn't supported, it falls back to **0.8 s**. ## Default language Sets the language for speech recognition. Pick **Auto** to detect it automatically, or lock it to a specific language for better accuracy when you always speak the same one. Over 40 languages are supported. ## Voice Choose the assistant's spoken voice — **Male** or **Female**. Used by **Voice → Text → Voice** and **Voice ⇄ Voice**. ## Speed Adjust how fast the assistant speaks, from **0.8×** (slower) to **1.3×** (faster). Default is **1.0×**. ## Noise reduction Match this to your hardware to reduce echo and background noise. | Option | Use when | |---|---| | **Off** | You have a clean studio setup or a hardware noise gate | | **Headphones** (default) | You're using a close-range mic — headset, lavalier, USB mic | | **Laptop / Speakers** | You're using a built-in laptop mic with speakers playing the response | ## Reset to defaults The dialog has a **Reset to defaults** button that restores: Voice ⇄ Voice mode, 0.8 s pause, Auto language, Male voice, 1.0× speed, Headphones noise reduction. You still need to **Save** to apply the reset. ## Tips - For very noisy environments, switch to **Voice → Text** — the text engine is more forgiving than the live speech-to-speech path. - If the assistant interrupts you too often in Voice ⇄ Voice, try **Automatically (semantic)** turn detection. - For dictating into a long message you'll edit, use **Dictation** with **Manual** sending. --- # App Builder *Create custom ERP data apps with natural language* ## What is the App Builder? The App Builder is a specialized agent in Operator that lets you create small, focused ERP data applications — called **Operator Apps** — using natural language. Instead of writing code manually, you describe what you want—and the App Builder generates a fully functional app that integrates directly with ERP.net. ## What Are Operator Apps? Operator Apps are **single-page applications (SPAs)** designed for **internal corporate users**. They are lightweight, browser-based tools that run entirely on the client side — no server deployment or infrastructure is required. Each app is purpose-built for a specific task: a dashboard, a data entry form, a lookup screen, a status monitor, or any other focused interface that works with your ERP data in real-time. They are not intended as public-facing websites or customer portals — they are internal productivity tools for your organization's employees. ## ERP.net as the Default Data Model The App Builder is built around the [ERP.net](https://erp.net) data model. Every app you create can immediately work with real business objects — customers, products, sales orders, invoices, projects, and any other entity in your ERP.net instance — because the App Builder already understands ERP.net relationships, types, and conventions. This means: - **Out-of-the-box data** — apps are designed against proper ERP.net business objects, not anonymous spreadsheets or custom schemas. - **Zero setup integration** — your apps connect to the same live ERP.net instance you are already using in Operator, so they work immediately for the current enterprise company and user permissions. - **Business-ready design** — the AI knows how to build forms, dashboards, and workflows that match ERP.net entities and best practices. At the same time, you are not limited to ERP.net. You can build any Operator App you want — including apps that use external APIs, combine ERP data with third-party services, or do not touch ERP.net at all. ## Support Policy The App Builder follows a **self-service model**. AI-powered assistance inside Operator replaces traditional support — **AI-generated apps are not covered by ERP.net or Operator support**. You build and run them at your own discretion. By using the App Builder you accept the following principles: - **User Responsibility** — You are solely responsible for testing, securing, and maintaining your app. Verify behavior with real data before relying on it for business-critical work. - **AI Error Liability** — AI-generated code may contain mistakes, omissions, or unexpected behavior. You accept all risks arising from such errors. Always review the generated code and the live preview before deploying. - **Security** — You must configure security (permission policies, sharing scope, data exposure) to protect your data. The AI does not guarantee a secure configuration by default. Apps that read or modify ERP data inherit the permissions of the user running them — design accordingly. - **Code Ownership** — You own the code your apps generate. You can view it in the **Code** tab and export it to deploy elsewhere if you outgrow the App Builder. If you need a guaranteed, supported solution, build it as a traditional ERP.net customization or engage an ERP.net partner. The App Builder is intended for fast, internal, self-managed productivity tools. ## How It Works The App Builder uses a conversational workflow: 1. **Describe your app** — Tell the App Builder what you want in plain language. For example: *"Create a dashboard showing overdue invoices grouped by customer"*. 2. **Iterative design** — The App Builder generates the app and shows you a live preview. You can refine it by asking for changes: *"Add a filter for date range"* or *"Make the table sortable by amount"*. 3. **Deploy** — Once satisfied, deploy your app through one of the available deployment modes. ## Getting Started ### Who can use the App Builder The App Builder is available to: - **Global Power Users and above** — always available, regardless of which instance (if any) is connected. - **Instance Power Users and above** — available while an ERP.net instance where you have Power User or Admin role is connected. Disconnecting that instance (or switching to one where you only have Normal/External access) hides the App Builder. ### Starting the App Builder 1. Open the **agent selector** in the header bar (next to the Operator logo). 2. Select **App Builder** from the dropdown. 3. You'll enter **Creator Mode** — a clean workspace ready for a new app. 4. Describe your app in the chat and watch it come to life. ### The Agent Selector The agent/app dropdown in the header serves dual purposes: - **Select App Builder** — Switches to the App Builder agent in Creator Mode, ready to design a new app from scratch. - **Select an existing app** — Opens the app in **Execution Mode** for day-to-day use. From there, you can switch to **Design Mode** to make changes. ## Interface Modes The App Builder interface has several modes, accessible via the tab bar: | Mode | Description | |------|-------------| | **Create** | Shown when no app is selected. Describe a new app to build it. | | **Execute** | Run and interact with your app as an end user would. | | **Design** | A split view (chat + preview) for iterating on your app's design and functionality. | | **Code** | View and inspect the generated source code (the app's *source files*). | | **Cloud** | Pro apps only. Manage the app's *stored files* — documents and data the app reads at runtime — plus backend tables, request proxy settings, and additional pages. See [Pro App File Storage](pro-apps-files), [Pro App Requests](pro-apps-requests), and [Pro App Pages](pro-apps-pages). | | **Properties** | Configure app metadata: name, slug, description, and categories. | | **Deploy** | Configure how and where your app is deployed. | Source files and stored files are different things: source files are the app's program code, stored files are data. When you mention a file by name in chat, the App Builder treats it as a stored file. ### Design Mode Design mode provides a **30/70 split view** — the chat panel on the left and a live app preview on the right. As you describe changes, the preview updates in real-time. Use the **Refresh preview** button (right side of the tab bar) to force a reload if needed. **Testing on a real record.** Apps that are placed as a side panel on a record get a record button next to the refresh button (it reads "No record" until you pick one). Choose an entity type, search for a record by name or paste its id, and the preview runs as if the app had been opened on that record — the same way a side panel is opened from a document form in the ERP.net Web Client. The choice is saved with the app for that instance, so it comes back whenever you continue designing, on any computer; **Clear record** returns the preview to the empty state. Apps that are menu or navigation entries do not show the button, since they are never opened on a record. ### Execution Mode Execution mode shows your app full-width, exactly as end users will see it. This is the default view when selecting an existing app from the agent dropdown. Operator opens existing apps directly in Execute mode for faster startup, and only loads the related design conversation when you switch to **Design**, **Code**, **Properties**, or **Deploy**. ## What Apps Can Do Apps built with the App Builder can work with live ERP.net data, call AI, and integrate with external services. See [API Access in Apps](app-builder-api-access) for details on the ERP.net Domain API, data limits, error handling, and external REST API calls. In short, apps can: - **Query data** — Fetch and display records from any ERP entity - **Create records** — Build forms that create new entries in the system - **Update records** — Modify existing data with validation - **Display dashboards** — Visualize data with charts, tables, and summary cards - **Filter and search** — Add interactive controls for data exploration - **Respond to context** — React to the connected instance and enterprise company - **Call AI** — Invoke Pure AI for one-shot completions or run full Operator agents (built-in or user-defined) with tools and capabilities. See [AI in Apps](app-builder-ai). - **Call external APIs** — Integrate third-party services using `fetch()` or `window.operator.corsFetch()`. See [API Access in Apps](app-builder-api-access). ## Best Practices - **Start simple** — Describe the core function first, then iterate with refinements. - **Be specific** — Mention exact entity names, fields, and filters you need. - **Test with real data** — Connect your instance and verify the app works with actual records. - **Use descriptive names** — Give your app a clear name and description for easy discovery. - **Accept refactor suggestions** — If the App Builder suggests reorganising an existing app into smaller files, accept it. The refactor itself is a heavy operation and typically consumes **20–100 credits** on its own (proportional to app size, since the AI rewrites many files across several turns). That upfront cost is quickly offset: every subsequent edit on the refactored app becomes noticeably cheaper because the AI no longer re-reads a monolithic file for each change. The only reason to decline is if you don't plan to keep developing the app. ## The Builder Moves You to the Right Tab When something you asked for lives on another tab, the App Builder switches your workspace there and tells you why — for example to **Properties → Pro App** when your request needs a Pro app (backend tables, stored files, secrets, public access), to **Cloud** after it changed stored files or tables, or to **Deploy** when it is time to publish. It also knows which tab you are looking at, so short instructions like "this is wrong" or "save this" are interpreted against the surface in front of you. ## Diagnostics and API Logging The **Diagnostics** tab shows what the app did at runtime: its own event logs, browser console output, and the API requests it made. Failed requests are always recorded. Successful requests are only recorded while API logging is switched on, which happens for a limited period so nothing stays on by accident. You do not have to flip that switch yourself — just ask the builder: - *"Turn on API logging for the next 30 minutes"* — it opens the window and asks you to reproduce the problem. - *"Check what the app sent when I saved the order"* — it reads the captured requests and explains what went wrong. - *"Turn API logging off"* — it closes the window immediately. This is most useful when a request *succeeds* but the result looks wrong; for plain errors the builder can read the logs straight away. ## Work Plans for Large Jobs For jobs that clearly need many steps — a multi-file refactor, a performance analysis of a large app, a feature that touches several views — the App Builder writes itself a **work plan** first. It appears as a *Work plan* strip above the message box: a completed/total counter with the step currently in progress. Click it to expand the full list and see what each finished step actually did. Each new request starts a fresh work plan — steps from your earlier requests are cleared automatically, while pauses and "Continue" within the same request keep the plan intact. The plan's real value shows up on long-running work: - **Pauses are cheap.** If the run pauses and asks you to continue, the plan is waiting when it resumes — the builder picks up at the next step instead of re-reading files it already analyzed. What it learned is recorded in one-line notes on each completed step, so no work is repeated. - **Nothing is silently dropped.** If the builder discovers mid-job that the plan no longer makes sense, it rewrites the remaining steps while keeping everything already completed. You always see the current state of the plan. Small and medium apps need no plan — the builder only creates one when the work genuinely warrants it. ## Multiple Conversations per App Each app supports **multiple conversations** — one per feature, screen, or sub-project. Splitting the work keeps context focused, cheaper, and easier to resume. Open the **Conversations** tab in the app panel to switch between them or start a new one. See [Conversations](/help/builder-conversations) for the full mechanics, actions, and examples. ## Next Steps - Learn about [Deployment Options](/help/app-builder-deployment) for publishing your apps - Manage your apps on the [Apps Page](/help/app-builder-management) - Organize your work with [Conversations](/help/builder-conversations) --- # Conversations *Split your build work into focused threads — in both the App Builder and the Agent Builder* Both the **App Builder** and the **Agent Builder** support **multiple conversations per app or agent**. Instead of building, refactoring, and fixing things in one ever-growing thread, you split the work into focused conversations — one per feature, screen, or refinement pass — and switch between them at any time. Open the **Conversations** tab in the builder panel (next to Properties / Design) to see them all. ## Why multiple conversations help - **Focused context** — the AI works best when the recent history is relevant to what you're doing now. A dedicated conversation for "checkout flow" or "tighten the sales agent's instructions" stays on-topic and doesn't drag in unrelated decisions from earlier. - **Cheaper, faster turns** — shorter histories mean smaller prompts, lower credit usage, and quicker responses. - **Easy to resume** — come back days later and pick up exactly where you left off on a specific area, without scrolling past unrelated chatter. - **Safer experimentation** — try a risky refactor or a rewrite of an agent's instructions in a new conversation; if it doesn't pan out, the rest of your work stays untouched. ## What you'll see The Conversations tab lists every conversation for the current app or agent, grouped by: - **Current instance** — conversations on the ERP.net instance you're connected to right now. Click any of them to switch. - **Other instances** — conversations bound to a different instance. They're shown for reference; to open one, switch to that instance from the top bar first. - **Archived** — hidden by default; toggle **Show archived** to see them. For each conversation you get the title, instance, when it was **created**, and when it was last **updated**, plus badges for the current one and any that are still running. > **Why does my conversation look empty?** If you open a builder project and the conversation appears blank, check whether you switched the connected ERP.net instance. Each instance has its own set of conversations, and changing the instance automatically creates or swaps to the matching conversation for that instance. Open the **Conversations** tab to confirm which instance the current conversation belongs to, and switch back to the original instance if you want to see the previous history. ## Actions - **New conversation** — top-right button. Starts an empty conversation for the same app or agent on your current instance, and drops you straight into the Design view so you can start typing right away. - **Switch** — click any conversation row on the current instance to open it. - **Archive** — from the row menu (`⋯`). Hides the conversation from the default view; the data is kept and you can restore it any time. - **Restore** — toggle **Show archived**, then choose **Restore** from the row menu. You can't archive the conversation you're currently in — open another one first. ## How it differs between the two builders The mechanics are the same; the *grain* of a conversation is different. - **In the App Builder** — one conversation per feature, screen, or sub-project of the app: *"Layout & navigation"*, *"Customers list"*, *"Customer detail page"*, *"Bulk import"*. Each conversation builds and refines a slice of the app. - **In the Agent Builder** — one conversation per round of design work on the agent: *"Initial setup"*, *"Tighten the instructions"*, *"Add calendar capability"*, *"Rework the greeting"*. The latest design conversation for an agent reopens automatically when you come back to it. In both cases, switching instances automatically swaps to the matching conversation for that instance (or starts a clean one if none exists yet). ## Example: building a small CRM app A typical App Builder flow with four parallel conversations: 1. **"Layout & navigation"** — set up the page structure, sidebar, theme. 2. **"Customers list"** — wire up the customers table, search, and filters. 3. **"Customer detail page"** — single-record view, related orders, edit form. 4. **"Bulk import"** — a one-off conversation for a CSV import screen. Each conversation keeps its own back-and-forth with the AI. When you ask the customers-list conversation to "make the status column sortable", it doesn't get distracted by an earlier debate about the navigation icons. When the bulk import is shipped and you don't expect to touch it for a while, archive that conversation to keep the list tidy. If a bug comes back later, restore it and the full history is still there. ## Example: refining a Sales Pipeline agent A typical Agent Builder flow over a couple of weeks: 1. **"Initial setup"** — create the agent, pick the base agent, write the first instructions and greeting. 2. **"Tighten Q4 focus"** — rework the instructions to prioritise high-value deals and stalled opportunities. 3. **"Add calendar capability"** — turn on calendar access and adjust instructions for booking follow-ups. 4. **"Polish the welcome screen"** — refine the greeting message and quick-action buttons. Each conversation is a focused design session. Archive the ones that are clearly done; reopen any of them later if you want to revisit a decision. ## Tips - **Name conversations clearly** — rename early so the list stays scannable as it grows. - **One concern per conversation** — resist the urge to dump everything into one thread; split as soon as you start a noticeably different task. - **Archive aggressively** — anything finished and stable can be archived. Nothing is deleted. - **Pair with [Version History](/help/version-history)** — conversations split the *work*, versions snapshot the *state*. Together they give you fast iteration and instant rollback. ## Keeping long conversations affordable Long builder threads grow expensive because the whole history is re-read at the start of every new request. If a conversation has become very long, set **App Builder context depth** in [Settings](/help/settings) → *AI-enhanced* to a number such as `10`. The builder then starts each new request from your last ten exchanges instead of the entire thread, while still using its project memory for the overall picture. Leave the field empty to keep the default behaviour. ## Related - [App Builder Overview](/help/app-builder) - [Managing Apps](/help/app-builder-management) - [Agents Overview](/help/agents) - [Creating Agents](/help/agents-creating) - [Conversations & History](/help/ui-conversations) — the same concepts for regular agent chats --- # API Access in Apps *How Operator Apps talk to ERP.net and other services* Apps built with the App Builder can read and write ERP.net data through the **ERP.net Domain API**, and they can also call external REST APIs when needed. This topic explains how both work, what limits apply, and how to handle errors. ## What Apps Can Do with ERP.net Data Apps built with the App Builder have access to the ERP.net Domain API (OData v4), enabling them to: - **Query data** — Fetch and display records from any ERP entity - **Create records** — Build forms that create new entries in the system - **Update records** — Modify existing data with validation - **Display dashboards** — Visualize data with charts, tables, and summary cards - **Filter and search** — Add interactive controls for data exploration - **Respond to context** — React to the connected instance and enterprise company - **Call AI** — Invoke Pure AI for one-shot completions or run full Operator agents (built-in or user-defined) with tools and capabilities. See [AI in Apps](app-builder-ai). - **Run server-side scripts** — Execute server-side JavaScript on the connected ERP.net instance for work that is more efficient to run next to the data, such as batch processing, transformations, or multi-step operations. This runs with the user's token and permissions — it does not grant elevated access. ## Data Volume Limits App Builder apps are lightweight client-side applications with strict data limits to ensure performance and stability: - **Maximum 1,000 rows per request** — Each API call can return at most 1,000 rows. Always apply filters to keep result sets within this limit. - **Maximum 10,000 rows in memory** — The app should never accumulate more than 10,000 rows across all loaded data sets combined. If your use case requires processing larger volumes of data, consider these strategies: - **Narrower filters** — Use date ranges, status filters, or other criteria to reduce the data set. - **Paginated views** — Load one page of data at a time without keeping all pages in memory. - **Summary queries** — Use aggregate or summary data instead of loading raw detail rows. - **Server-side processing** — Offload heavy data processing to the ERP system rather than pulling everything into the browser. ## Summaries and Totals (Server-Side Grouping) Instead of loading rows and adding them up in the browser, an app asks ERP.net for the grouped result. This is the recommended way to build KPIs, charts, trends, and per-group breakdowns: the numbers cover every matching record, and a single request replaces thousands of rows. ```js // Orders per month const res = await operator.aggregate({ entity: 'Crm_Sales_SalesOrders', group_by: [{ field: 'DocumentDate', interval: 'yearmonth', alias: 'Month' }], aggregate: [{ op: 'count', alias: 'Orders' }] }); console.log(res.value); // [{ Month: '2026-01', Orders: 42 }, ...] ``` What you can ask for: - **Group by** a field, a related record (`SalesOrder/Customer`), or an interval — `year`, `yearmonth`, `date`, or `firstchar`, and only these. Use `yearmonth` for monthly charts and `date` for daily charts; there is no `month` or `day` interval. - **Aggregate** with `count`, `sum`, `min`, `max`, `average`, or `countdistinct`. `average` is computed from server-side sum/count and returned under your alias. - **Filter first** using the same structured conditions as a normal query — the filter applies before grouping. - **Expand grouped references** so a customer group carries its readable name, not just an identifier. Rules to keep in mind: - Amounts and quantities are grouped **per currency and per unit** — one line per measure, never mixed. - Groups come back **unordered**; sort in the app for "top N" views. - Requires **ERP.net 27 or later**. On older instances the call rejects with a readable message naming the instance version and the code `AGGREGATION_UNSUPPORTED`; the App Builder knows the connected version up-front and designs around narrow filtered queries instead. ## Domain API Transactions The ERP.net Domain API allows only **one open transaction per session**. If an app opens a transaction (for a multi-step write that must be atomic) and fails to close it after an error, the session becomes unusable for any further transactional work until it expires — every later attempt fails with *"Maximum allowed transactions for this session have been reached."* The App Builder is instructed to avoid transactions when a single write would do, and — when one is genuinely needed — to wrap it in a `try / catch / finally` block so the transaction is always rolled back on error. You don't need to ask for this behavior; the App Builder applies it automatically. If you ever see this error from an older app, regenerate or patch it in the App Builder to pick up the safer pattern. ## Error Handling for ERP.net Calls When `window.operator.fetch(...)` fails, the rejected `Error` carries the exact ERP.net server message, so apps should surface it to the user instead of a generic "failed" toast. The error object includes: - `error.message` — the ERP.net server message (already in the instance's language, e.g. *"Вие нямате достъп до обект Gen_Products(***73d7a)"*). - `error.isErpError` — `true` when ERP.net rejected the request, `false` for transport/authentication failures. - `error.status` — HTTP status returned by ERP.net (e.g. `403`, `500`). - `error.statusText` — friendly label (e.g. *"ERP.net permission denied"*, *"ERP.net rejected the request"*). - `error.code`, `error.type`, `error.details` — when ERP.net provides them. Apps generated by the App Builder follow this pattern automatically: ```js try { await window.operator.fetch('/Production_Technologies_RecipeIngredients', { method: 'POST', body: payload, }); } catch (e) { if (e.isErpError) { toast.error('ERP.net rejected the change', { description: e.message }); } else { toast.error('Could not reach ERP.net', { description: e.message }); } } ``` Most "the app can't save to ERP.net" reports are in fact ERP.net permission errors — the connected user lacks read or write access on a referenced entity. The full error is also recorded in the app's runtime logs (visible to the App Builder agent), which usually points to the exact missing permission. The same `e.message` also carries proxy-side reasons such as *"Your connection to ERP.net expired and could not be refreshed. Please reconnect the instance."* or *"No ERP.net instance is currently selected."* — apps do not need any special-case code; surfacing `e.message` is always meaningful. These improvements apply live to every existing app on the next page reload — no rebuild or App Builder edit is required. ### Automatic request serialization ERP.net rejects concurrent calls from the same session with HTTP 429. To prevent this, Operator automatically serializes every `window.operator.fetch()` call inside the app — even if the app code accidentally fires them in parallel (e.g. `Promise.all([...])`), Operator queues them and sends one at a time. App authors should still write sequential `await` code for clear loading and error states, but this safety net protects existing apps from accidental 429s with no rebuild needed. ### Connection validation on app start When a user opens an app at `/app/:slug`, Operator validates the active ERP.net connection before mounting the app iframe. If the access token is expired, Operator silently attempts to refresh it. If the refresh fails, the app does **not** load — instead, Operator displays a full-screen *"Session expired for {instance}"* overlay with a **Reconnect** button that walks the user through the ERP.net sign-in flow. As soon as sign-in completes, the iframe boots with a fresh token and the app runs normally. App authors do not need to handle this case in code. ## External API Access App Builder apps can call external REST APIs directly using the standard browser `fetch()` API — no special SDK needed. This is useful for integrating third-party services, public data sources, or custom backends alongside your ERP data. ### How It Works Use `fetch()` as you would in any web application: ```javascript const response = await fetch("https://api.example.com/data", { headers: { "Authorization": "Bearer YOUR_TOKEN" } }); const data = await response.json(); ``` ### CORS Restrictions Apps run in a browser sandbox, so standard **CORS (Cross-Origin Resource Sharing)** rules apply: - If the external API includes an `Access-Control-Allow-Origin` header, you can call it directly with `fetch()`. - If it does **not** (e.g. EU VIES, many government APIs), the browser blocks the response. For these cases use **`window.operator.corsFetch(url, options)`** — Operator forwards the request server-side and returns the response wrapped in CORS headers your app can read. ```js const res = await window.operator.corsFetch( 'https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ countryCode: 'BG', vatNumber: '121084091' }), } ); if (res.ok) console.log(res.json()); ``` `corsFetch` is **not** an open proxy: - Only signed-in Operator users can call it. - Limited to 60 requests / minute / user. - Sensitive headers (`Authorization`, `Cookie`) are stripped before forwarding, so **never use it for APIs that require a secret API key** — build a dedicated backend function so the secret stays server-side. - Internal hosts (`*.erp.net`, `*.supabase.co`, `*.lovable.app`, `localhost`, private IPs) are blocked. ### Tips - **Public APIs with CORS** (weather, exchange rates) — call directly with `fetch()`. - **Public APIs without CORS** — call through `window.operator.corsFetch()`. - **APIs that need a secret key** — neither path is safe in client code; ask for a dedicated server function. - **ERP.net data** should always be accessed through `window.operator.fetch()`, which handles authentication and proxying automatically. - **Sequential requests** — As with ERP API calls, avoid concurrent requests to external APIs. Use `await` for each call to prevent rate limiting or ordering issues. ## Opening Another App An app can send the user straight into **another app** they already have access to — useful for hub-and-spoke setups, launchers, or a "back to the main app" link. ```js // Open another app by its slug (as shown in My Apps) await window.operator.apps.open('sales-overview'); // Open it in a new tab/window instead of replacing the current view await window.operator.apps.open('sales-overview', { newTab: true }); ``` Build a launcher from whatever the signed-in user can actually open: ```js const apps = await window.operator.apps.list(); // [{ slug: 'sales-overview', name: 'Sales Overview', description: '…' }, …] apps.forEach(app => addTile(app.name, () => window.operator.apps.open(app.slug))); ``` ### How it behaves - **Same running mode.** Inside an installed app, the target opens in the same installed window. In full screen, it opens full screen. Inside the App Builder preview, it opens in a new tab so the builder is never hijacked. - **Same instance.** The target app runs against the ERP.net instance the user is currently working in. - **Access is respected.** Only apps shared with the signed-in user can be opened or listed. If the slug is unknown or the user has no access, the call fails with a clear message — wrap it in `try/catch` and show a friendly note. Just tell the App Builder which app to open ("add a button that opens the Deliveries app") — it will look up the correct slug and generate the call for you. ## Hosting Another App Inside Yours Instead of navigating away, an app can **host another app in a panel** — a workspace app that shows a report app on the right, a dashboard that tiles several small apps, or a tabbed shell around existing apps. ```js // Fill a container with another app await window.operator.apps.embedInto('#report-panel', 'sales-overview'); ``` For full control over the iframe, get the ready-to-run HTML instead: ```js const child = await window.operator.apps.embed('sales-overview'); const frame = document.createElement('iframe'); frame.style.cssText = 'width:100%;height:100%;border:0'; document.getElementById('report-panel').appendChild(frame); frame.srcdoc = child.html; // child.slug, child.name are also returned ``` A tabbed workspace hosting two apps: ```js const tabs = { deliveries: 'deliveries-daily', sales: 'sales-overview' }; async function showTab(key) { try { await window.operator.apps.embedInto('#workspace', tabs[key]); } catch (e) { document.getElementById('workspace').textContent = e.message; } } showTab('deliveries'); ``` ### How it behaves - **The hosted app is fully alive.** It keeps its own ERP data access, AI calls, email and logging — everything routes through Operator exactly as if the app were opened on its own. - **Same user, same instance.** The hosted app runs as the signed-in user, against the instance currently in use, and only apps shared with that user can be hosted. - **Its own Cloud features and data.** A hosted Pro app uses its own tables, stored files, web requests and procedures — not the host's. The host app does not need to be Pro. Example: a free "System Setup" app can host a Pro "Courier Integrations" app, and the courier settings load from the courier app's own tables. - **Works everywhere.** Identical behaviour in the App Builder preview, full screen and installed (PWA) mode. - **One level only.** A hosted app cannot host a further app, and an app cannot host itself. Just describe what you want ("show the Sales Overview app in a panel next to my order list") — the App Builder picks the right slug and writes the embedding code. ## Related - [App Builder Overview](app-builder) - [Referencing Other Apps](app-builder-referencing) — reusing another app's code while building - [ERP.net with Operator Apps](/help/erpnet-apps) — how apps reach your live business data --- # Deployment Options *Deploy your apps across your business stack* ## Overview Apps built with the App Builder can be deployed in multiple ways, making them accessible wherever your team works. Each deployment mode serves a different use case—from quick internal tools to marketplace-published applications. ## Deployment Modes ### 1. Inside Operator The simplest deployment. Your app runs directly within the Operator interface, accessible by selecting it from the agent/app dropdown in the header. This is ideal for personal tools and quick utilities. **How to access:** Select the app from the agent dropdown → it opens in Execution Mode. ### 2. Full-Screen Apps can be launched in a dedicated full-screen browser tab using a direct URL. This is useful for apps that need more screen space or that you want to bookmark for quick access. **URL format:** ``` https://erpnet-operator.lovable.app/?app={slug} ``` For instance-specific execution, the URL can include the instance parameter: ``` https://erpnet-operator.lovable.app/?app={slug}&instance={base_url} ``` These URLs are bookmarkable and can be shared with other users. **Installable to the home screen.** Full-screen apps can be installed as their own app on the phone or desktop (via the browser's "Install app" / "Add to Home Screen"). Each installation is scoped to one app on one instance — the same app installed against a different instance appears as a separate icon. Every installed app uses a shared Operator-family tile (rounded square with the Operator mark and the app's initials) so the whole set reads as one family on the home screen. No offline support is included. Installable apps run on a dedicated address (`app.operator.net/a/{app}/{instance}`) so they are completely separate from the main Operator site (`operator.net`) — installing Operator will never capture your app icons, and installing an app will never capture Operator. Because the two live on different addresses, opening a full-screen app while signed out will bounce you through the main Operator sign-in page and then automatically return you to the app; you never lose the URL you started from. Apps installed before the dedicated app address was introduced may keep their old shortcut details even after the browser cache is cleared. Remove that old shortcut and install the app once from its current full-screen page; future launches then use the app name and icon stored by Operator. ### 3. ERP.net Web Client An app can be placed inside the ERP.net Web Client in three different ways. You configure them in the App Builder under **Deploy → Web Client Integration Points**, then press **Deploy to Web Client**. One app can use several placements at the same time. | Placement | Where users see it | What you pick | Needs ERP.net | |-----------|--------------------|---------------|---------------| | Main menu | As an application in a top-level category of the Web Client menu | A menu category | 26.2 or newer | | Forms navigation | In the Extensions section of one Forms module's navigation menu | A Forms module (namespace) | 27.1.1.9 or newer | | Entity side panel | As a panel on the right of record forms | A repository, or nothing for all record forms | 27.1.1.9 or newer | **Main menu** — best for standalone applications everybody should find on their own. *Example:* a "Delivery planner" app placed in the **Logistics** category appears next to the standard Logistics applications. **Forms navigation** — best for an app that belongs to one area of work. *Example:* a "Quote approvals" app registered for the `Crm.Sales` module appears in the Extensions section of the Sales navigation, together with the standard Sales forms. **Entity side panel** — best for an app that adds context to the record the user is looking at. The app is told which record is open (the repository and the record id), so it can load the right data by itself. *Example:* a "Customer risk score" app registered for `General.Contacts.Parties` opens as a panel beside every customer form; leaving the repository empty shows the panel on every record form. **Version differences.** Each placement requires a minimum ERP.net version. Operator reads the version of the connected instance and marks any placement the instance is too old for — both in the editor and in the Deploy confirmation. You may still save and deploy such an entry (useful when preparing for an upcoming upgrade); it simply will not appear until the instance is updated. **Set while the app is built.** When the App Builder builds an app whose place is evident — a document printout panel, a screen for one module, a standalone application — it fills the placement in for you and says in one line where the app will appear and why. Nothing is registered with your instance at that point: the entry simply waits on the Deploy tab, and you can edit or remove it before deploying. **Guess with AI.** When an app has no placement yet, the **Guess with AI** button proposes both the placement and its target, based on everything known about the app — its name and description, its display form, who can open it, and, for Pro apps, its pages, tables, web requests and memory notes. The suggestion always comes with a short explanation of why that placement was chosen. It appears as a message right after the suggestion and stays saved as the note on the entry, so you can review the reasoning later and change the placement if you disagree. *Example:* for a phone-shaped app showing delivery risk for the open order, the suggestion is the record side panel on sales orders, explained as "The app provides delivery risk and margin insights specifically for the open sales order, and its phone display form is optimized for the side panel." ### 4. ERP.net Marketplace For apps intended for broader distribution, you can publish them to the ERP.net Marketplace. This makes your app discoverable and installable by other ERP.net users and organizations. Publishing to the Marketplace involves additional review and quality requirements to ensure a consistent experience for all users. ## Choosing a Deployment Mode | Use Case | Recommended Mode | |----------|-----------------| | Personal productivity tool | Inside Operator | | Standalone dashboard | Full-Screen | | Team-wide navigation item | Web Client — main menu | | Tool belonging to one module | Web Client — Forms navigation | | Contextual data on a record | Web Client — Entity side panel | | Public distribution | Marketplace | You can deploy the same app in multiple modes simultaneously. For example, an app might be available both in the Web Client main menu and as a full-screen bookmark. ## Open in New Tab The **Deploy** tab in the App Builder includes an **Open in New Tab** feature that generates a URL with both the app slug and instance parameters pre-configured. This provides a quick way to test full-screen deployment or share a direct link with colleagues. --- # Managing Apps *Organize, edit, and manage your custom applications* ## The Apps Page All your custom apps are managed from the **/apps** page. This is your central hub for viewing, organizing, and managing every app you've built with the App Builder. The Apps page displays your apps as cards, showing each app's name, description, and categories. ## Opening and Editing Apps There are two ways to open an existing app: ### From the Apps Page Click the **Design** button (pencil icon) on any app card to open it in the App Builder's Design mode. This resumes the most relevant conversation for that app, so you can continue iterating where you left off. ### From the Agent Selector Use the **agent/app dropdown** in the header bar (next to the Operator logo) to select any of your apps. Selecting an app opens it in **Execution Mode** by default — the full-width view for day-to-day use. This launch path skips loading the design conversation until you switch to **Design Mode** or another build tab, so apps open faster. ## Creating New Apps To create a new app: 1. Navigate to the **/apps** page. 2. Click the **Create App** button. 3. You'll be taken to the home screen with the App Builder selected in **Creator Mode**. 4. Describe your app in the chat to start building. Alternatively, select **App Builder** from the agent dropdown in the header at any time to enter Creator Mode. ## Duplicating Apps You can make your own copy of any app you own — or that has been shared with you at **Clone** level or higher. There are two ways to duplicate: - From the **/apps** page, open the actions menu (⋯) on any app card and click **Duplicate**. - Inside the App Builder, open the **Properties** tab and click **Duplicate** in the *Duplicate App* section. A confirmation dialog opens with editable **Name** and **Slug** fields. The defaults append today's date — for example `My App (2026-05-30)` and `my-app-2026-05-30` — and if there is already an app with that name/slug, a numeric suffix is added (`… (2)`, `…-2`, and so on). If the source app already ends with a date suffix, that date is replaced rather than stacked. The new app is created under your account; files (code) and basic settings (description, categories, form factor, safe-mode flag) are copied. **Sharing assignments, Web Client integration points, conversations, statistics, and deployments are not copied** — the new app starts clean. After cloning you are taken straight into Design mode for the new app. ## Deleting Apps To delete an app: 1. Open the app in the App Builder. 2. Navigate to the **Properties** tab. 3. Scroll to the **Danger Zone** section. 4. Enter the app's slug to confirm deletion. 5. Click delete. > **Note:** Deleting an app archives all associated conversations. The conversations are preserved for billing purposes but will no longer be visible in your conversation history. ## Pro Apps Apps can run on one of two tiers: - **Free** — the default. The app runs as a client-side app. - **Pro** — the app gets a **managed backend**, adding storage, secrets, server procedures, HTTP proxy, logging, public access, and custom domains. These capabilities are being rolled out progressively. > **Credits:** Pro apps consume AI credits — starting at **1 credit per day**, and increasing depending on how much the app is used. To switch tiers, open the app in the App Builder, go to the **Properties** tab and use the **Pro App** section: - On a Free app, click **Upgrade to Pro** and confirm. - On a Pro app, click **Downgrade to Free** to return to the Free tier. The managed backend features stop being available and the app no longer consumes credits for them. Only the app owner can change the tier. Pro apps show a **Pro** badge in Properties and in the app list. ## App Properties Each app has configurable properties accessible from the **Properties** tab: | Property | Description | |----------|-------------| | **Name** | Display name shown in the app list and agent selector | | **Slug** | URL-friendly identifier used in deployment URLs | | **Description** | Brief explanation of what the app does | | **Categories** | Tags for organizing and filtering your apps | | **Display form** | Target device shape for the App Builder preview — **Phone** (390 × 844), **Tablet** (820 × 1180), **Desktop** (1280 × 800), or **Wide screen** (1920 × 1080). The standalone runtime always uses the real device viewport. | --- # AI in Apps *Let your apps think, classify, summarize, and run full Operator agents on demand* Apps you build with the App Builder can use AI as a built-in capability — no extra setup, no API keys to manage. When you describe your app, simply tell the App Builder where AI should be involved, and it will wire it up for you. There are two flavors of AI you can use, and the App Builder picks the right one based on what you ask for. ## Pure AI — for one-off thinking tasks Use this when your app needs a single, focused answer from AI: classify something, extract a value, summarize text, or look at one image or document. Examples of what to ask for in your app description: - *"When a customer message arrives, use AI to classify it as Complaint, Question, or Compliment."* - *"Add a button that summarizes the selected sales order notes into one paragraph."* - *"When the user uploads an invoice photo, extract the total amount and invoice number."* - *"Translate the product description into French."* Pure AI is fast and cheap. It does not use any tools, does not see your ERP data on its own, and does not remember previous answers — each call stands alone. ### Choosing how hard the AI thinks You can tell the App Builder how much effort the AI should put in: - **Fastest** — trivial sorting and tagging. - **Fast** *(default)* — most everyday tasks. - **Smart** — careful analysis, multi-step reasoning. - **Expert** — the hardest problems where accuracy matters most. Just say it in plain language: *"Use the Smart level when generating the recommendation summary."* ### Ready-to-use results instead of prose If your app needs the answer as data rather than as text — to fill a form, draw a chart, or filter a list — just say so: *"the result should come back as ready-to-use data, not as a paragraph."* The App Builder will ask AI for a structured result and your app receives fields it can use directly. ### Number crunching with Python When the task is real computation — totalling hundreds of rows, grouping, reconciling, spotting outliers, or producing a spreadsheet or chart file — ask for it plainly: *"analyse the uploaded price list with Python and show the totals per category."* The AI then writes and runs Python on your data, and **your app uses what the calculation produced**, not what the AI wrote in words — the AI's text is only a short summary for people to read. That means the numbers are computed, not estimated. Very large results are handed over as a generated file behind the scenes, and your app still simply receives the complete result — nothing is trimmed to make it fit. Any file the calculation creates (spreadsheet, CSV, chart image) comes back as a download link that stays valid for about three days. Two rules of thumb: - Reading a document or classifying free text → ask for a structured result. - Computing over many rows or producing a file → ask for Python. The two cannot be combined in one call; the App Builder picks the right one for each step. ## Full agent conversations — when AI needs to do real work When a single answer is not enough — for example, you need the AI to **look up data, run tools, follow rules, or hold a conversation** — your app can run a full Operator agent in the background, exactly like the assistant you talk to in the main Operator chat. Examples of what to ask for: - *"Add a chat panel where the user can talk to the **Business Specialist** about the currently selected customer."* - *"When the user clicks 'Analyze', let the **System Architect** agent investigate the issue and write a report."* - *"Use my custom **Onboarding Coach** agent to guide the user through the steps."* - *"Open a conversation with the **Advisor** so the user can ask product questions without leaving this app."* The agent has access to all of its normal tools and capabilities — querying ERP data, searching documentation, sending email, calling automations, and so on — within the limits of what the running user is allowed to do. ### Picking the agent You can use any of the built-in agents: | Agent | Good for | Who can use it | |-------|----------|----------------| | **Advisor** | Product knowledge, ERP.net Q&A | Everyone | | **Business Specialist** | Everyday tasks against your data | Anyone with an instance connection | | **System Architect** | Configuring the system, complex problem solving | Power Users and above | | **Partner** | Advanced consulting work | Certified partners | | **Sales Executive** | Customer-facing self-service | Client-mode connections | Or you can point your app at one of **your own agents** — both the ones you created and the ones other people have shared with you. Just refer to the agent **by name** when describing the app (e.g. *"use my **AI Asset Assistant** agent to process the file"*) and the App Builder will look it up and wire it in for you. End users of the finished app **never see or type an agent ID** — the agent is baked into the app at build time. See [Creating Agents](agents-creating) for how to build your own. You can also tell the App Builder to **limit which capabilities** the agent uses inside the app — for example, *"only let the agent use Knowledge and Data Records, nothing else."* When you reference one of **your own agents**, the conversation runs with **its** base persona, **its** reasoning level, and **its** capability list — exactly the way the agent is configured under [User Agents](agents). The app can only **narrow** that list (drop capabilities); it cannot add anything the agent itself isn't allowed to use. ### Read-only by default — opt in to write Conversations launched from an app run **read-only** by default — the agent can read ERP data, search documentation, look things up, but it cannot create, update, or delete records. This is a safety net for apps that only need to look at data. If your app legitimately needs the agent to write back — for example, *"create a Vehicle record from the uploaded photo"*, *"update the customer address"*, *"log a To-Do task"* — just say so when you describe the app: *"the agent should be allowed to update records"* (or *"…create assets"*, *"…log tasks"*, etc.). The App Builder will switch the conversation into write mode for you. The deployment-level read-only lock (set by your instance admin) always wins. If the instance is hard-locked read-only, no app can override that. ### Attaching files When the user uploads or selects a file in your app, you can pass it to the agent as part of the message. The agent sees the same file content as it would in a normal Operator chat — full image understanding, PDF parsing, spreadsheet contents, etc. — within the usual file-size limits. ### What the user sees Conversations started by an app are real Operator conversations. They show up in the user's normal chat history, and the user can revisit them later from the main Operator interface. ## Long-running analyses Heavy AI work — a Python analysis over thousands of rows, a large report, deep reasoning — can easily take **several minutes**. Operator waits for it automatically: the app keeps waiting in the background and receives the finished result whenever it is ready, up to a 15-minute ceiling. Nothing is lost after two minutes any more. What this means for your app: - Show a **progress indicator** ("Analysing products…") rather than a short timer or your own timeout. - Don't retry a call just because it is slow — a retry starts a second run and spends credits twice. - If a run genuinely fails, the app receives a clear reason instead of a generic connection error. Example wording for the App Builder: *"the product analysis can take a few minutes — show a spinner with a 'this may take a few minutes' note and don't time out."* ## Where the AI runs - AI calls are made by the Operator host on behalf of the running user. **No API keys** live in your app. - AI usage **counts toward the running user's normal AI credits**, just like regular chat. - A full agent conversation runs against **the instance the user has selected in the toolbar** at the moment the conversation is created. If you need a specific instance, make sure the user has it selected before triggering the AI work. ## Best practices - **Reach for Pure AI first.** It is faster, cheaper, and good enough for most tagging, extraction, and summarization tasks. - **Use a full agent only when the AI needs tools or a back-and-forth.** Running a full agent for a one-line classification is overkill. - **Pick the smallest agent that fits.** "Advisor" for product questions, "Business Specialist" for data work — using a heavier agent "just in case" wastes time and credits, and may not even be available to every user of your app. - **Match the agent to your audience.** If your app will be used by people without an instance connection, lean on Advisor or Pure AI rather than agents that require one. - **Keep files small.** When you ask AI to look at an image or PDF, the smaller the file, the faster the answer. - **Plan for failures.** AI can be rate-limited, denied by permissions, or run out of credits — ask the App Builder to **show a friendly message** if a call fails, instead of leaving the user staring at a spinner. ## Support policy The AI features described here are part of the App Builder, so the same self-service support policy applies — see the **Support Policy** section of the [App Builder overview](app-builder). You are responsible for testing AI-driven flows in your app and making sure the agent and capabilities you choose match the permissions of the people who will use it. --- # Referencing Other Apps *Point the App Builder at another app so it can reuse the code, layout, or logic you already built* While you are building an app in the App Builder, you can point the agent at **another app** you have access to. It will read that app's files and use them as a starting point for the app you're editing now — so you don't have to describe from scratch something you already got right somewhere else. ## How to use it - Type **`@`** in the App Builder chat input. A popover lists every app you can reference. - Only apps shared with you at **Clone** level or higher show up, and the app you're currently editing is excluded. - Pick one — the editor inserts an `@app:` mention into your message. - Send the message. The agent can now **list and read** the referenced app's files and **copy or adapt** them into the current app. - Writes always go to the current app. The referenced app is treated as **read-only**, regardless of your permission level on it. You can mention more than one app in a single message, but the clearest results come from referencing **one at a time** unless you're intentionally blending patterns from two apps. ## When to use it — examples The examples below are the whole point of this page. Copy them, adapt the app slug and the specifics, and you're done. ### Replicating similar UI (the most common reason) - *"Build a customers list page with the same layout, filters, and column styling as @app:sales-overview's opportunities page."* - *"Copy the dashboard header and sidebar from @app:ops-console and adapt the nav items to this app's routes."* - *"Match the card + detail-drawer pattern used in @app:crm-lite for showing tickets."* - *"Use the same login screen and empty-state illustrations as @app:field-service so the two apps feel like one product."* ### Replicating business logic - *"Reuse the VAT-and-discount calculation from @app:invoicing for this quote builder."* - *"Port the CSV import + validation pipeline from @app:bulk-import and adapt the column mapping to Products."* - *"Use the same approval-workflow state machine as @app:expense-approvals — draft → submitted → approved → paid."* - *"Copy the pricing-tier logic from @app:subscriptions and apply it to the plan picker on this page."* ### Reusing integrations and SDK wiring - *"Copy the mail-send setup from @app:notifications-hub and wire it into the 'Send quote' button here."* - *"Adopt the file-upload + preview component pattern from @app:document-vault."* - *"Reuse the ERP customer-lookup autocomplete from @app:sales-overview instead of building a new one."* ### Cross-app consistency - *"Align the typography, spacing, and button styles with @app:sales-overview so both apps feel like one product."* - *"Use the same date-range picker component and formatting as @app:reporting-hub."* ### Learning from a working example - *"Look at how @app:reporting-hub structures its chart components, then build something similar for this app's KPI page."* - *"Read @app:crm-lite's routing setup and use the same pattern here."* ## What the agent can and can't do with a referenced app **Can:** - List and read the app's files. - Copy or adapt code, layout, styling, and conventions into the current app. - Learn from how the referenced app is structured. **Can't:** - Modify, delete, or publish anything in the referenced app. - Trigger the referenced app's automations. - Read data the referenced app stores on behalf of its users. ## Tips - **Be specific about what to copy.** *"Copy the header layout"*, *"reuse the discount formula"*, *"port the CSV parser"* — much better than *"make it like @app:x"*. - **One reference at a time** unless you're deliberately blending two apps. - **Don't see an app in the popover?** It has to be shared with you at **Clone** level or higher. See [Managing Apps](/help/app-builder-management) for sharing levels. - **The referenced app can change.** If you copied code from it and the original later evolves, your app doesn't automatically follow — mention it again to pick up the newer version. ## Related - [App Builder Overview](/help/app-builder) - [Managing Apps](/help/app-builder-management) — sharing levels - [Conversations](/help/builder-conversations) - [AI in Apps](/help/app-builder-ai) > **Not the same as opening another app at runtime.** Referencing is a *build-time* tool — it lets the agent read another app's code. If you want your finished app to *navigate the user* into another app, see [API Access in Apps](/help/app-builder-api-access#opening-another-app). --- # Safe Mode *Recover an app that freezes the browser or loops in preview* ## What it is Safe Mode opens an app in the App Builder **without running its live preview**. The app's files are loaded so you can edit them in the **Code** tab and chat with the agent to revert or fix the problem — but the iframe that runs the app is never mounted, so a broken app cannot freeze the page, loop infinitely, or trap you out of your own work. The editor also watches the visible preview with a heartbeat while it is running. It allows 30 seconds for startup, then offers recovery options after about 15 seconds without a response. Use it whenever an app becomes unresponsive in the editor and you can no longer reach the Properties, Code, or Chat tabs through the normal preview view. ## When to use it - The app's preview hangs, crashes the tab, or burns CPU on open. - An infinite render loop reloads the editor before you can act. - A modal or script captures input and you cannot click out. - You just want to inspect or edit files without executing the app at all. ## Two flavors | Mode | Where it lives | Scope | Best for | |---|---|---|---| | **Session Safe Mode** | `?safe=1` URL parameter | This tab only — gone on next normal open | A one-time rescue so you can edit and ship a fix | | **Persistent Safe Mode** | `safe_mode` flag on the app | Every open, every device, until turned off | Apps that need ongoing work before they're safe to run again | Both flavors block the preview the same way. The difference is only how long the block lasts. ## Activating Safe Mode ### From the Apps page (recommended) Go to **/apps**, open the **⋯ (More)** menu on the app's row, and choose one of: - **Open in Safe Mode** — opens the app with `?safe=1` for this session only. The persistent flag stays off. - **Switch to Safe Mode** — flips the persistent `safe_mode` flag on the app. Every future open is in Safe Mode until you disable it. Apps with the persistent flag on show a **Safe Mode** badge next to their name on this page. ### From the URL Append `?safe=1` to any `/app/:id` URL: ``` /app/cbd1fec9-806a-4d84-82ff-f2cbb3db79d4?safe=1 ``` This works even if you cannot reach the Apps page menu — bookmark it for emergencies. ### From inside the app (Properties tab) If you can still reach the **Properties** tab, scroll to the **Safe Mode** card and flip the switch. This sets the persistent flag. ## Automatic freeze detection When the App Builder preview is visible, the editor listens for a heartbeat from the running app every second. A fresh preview gets 30 seconds to start and settle. After that, about 15 continuous seconds without a heartbeat shows a **"Preview is taking unusually long"** message. Monitoring pauses when you open another Builder tab or hide the browser tab, and resumes with a fresh observation window. The heartbeat uses the app's browser UI thread. A missing heartbeat therefore means the app may be busy or stuck; it is not proof of an infinite loop. The app itself is *not* stopped — it keeps running behind the message and the notice disappears by itself if it recovers. You have four choices: - **Wait** — hide the message and keep waiting. Nothing is restarted, and the notice will not come back for the next 30 seconds. - **Restart preview** — reload the app from scratch. - **Turn Safe Mode on** — enable the persistent `safe_mode` flag so the preview stays hidden while you fix the code. - **Ask the Builder to fix it** — stop the frozen app, switch to the **Chat** tab and immediately send the App Builder agent a message with the time of the freeze and the last console output, so the agent has the context it needs. This button is disabled while the Builder is already working on a previous request, so you cannot accidentally launch a second, overlapping turn. Once you hand the app to the Builder, the suspected stalled preview is **stopped completely** — it can no longer make the browser complain about an unresponsive page. As soon as the Builder saves a change, the preview starts again automatically so the agent can see and test the result. If the app stalls again during the fix, it is stopped again after the conservative detection window and a fresh report (with the newest console output) is available for the next "Ask the Builder to fix it" click. You can always use **Restart preview** to reload the app manually at any point. The freeze state and the last console logs are saved to the app's diagnostics, so the agent can see them when you ask for help. The preview also runs isolated from the editor, so an app stuck in an endless loop keeps the editor itself responsive — you can still chat, edit code and switch tabs while the frozen preview is being stopped. Once an app has frozen, it is never run inside the editor page itself; if the isolated preview cannot start, you get a **"Preview could not be started safely"** message instead. ## What you see in Safe Mode - The preview area shows a **"Preview disabled — Safe Mode"** placeholder with a label telling you whether it is *this session only* or *persistent*. - A banner above the tabs reminds you Safe Mode is on. - The **Code** tab works normally — edit, save, and the changes are stored. - The **Chat** tab works normally — ask the agent to fix the bug or revert to an earlier version. - The preview iframe is never mounted, so the broken code cannot execute. ## Disabling Safe Mode - **Session Safe Mode** — just open the app without `?safe=1` (e.g. click **Design** from the Apps page). The preview runs again immediately. - **Persistent Safe Mode** — turn it off from any of: - **Properties** tab → Safe Mode card → toggle off - **Apps page** → ⋯ menu → **Disable Safe Mode** - The **Disable Safe Mode** button shown in the fullscreen Safe Mode screen ## Avoiding confusion when both apply If a one-time `?safe=1` session is active **while the persistent toggle is off**, the Properties card shows an amber notice explaining the situation. Closing the tab or opening the app without the URL parameter is enough — you don't need to touch the toggle. ## Related - [Managing Apps](/help/app-builder-management) — overview of the Apps page and Properties tab - [Overview](/help/app-builder) — what the App Builder is and how preview rendering works --- # Version History *Track every change to your apps and agents — and roll back any version* Both the **App Builder** and the **Agent Builder** keep a full version history of every meaningful change. You can browse the timeline, save labeled checkpoints, restore any version in place, or branch a new copy from any version. ## When versions are captured | Trigger | Source | What happens | |---|---|---| | AI build turn completes | `AI turn` | A snapshot is taken automatically at the end of every successful turn that changed something. Identical snapshots are skipped. | | You click **Save current version** | `Saved` | A manual checkpoint, with an optional label. | | You restore a version in place | `Pre-restore` + `Restored` | The current state is auto-snapshotted **before** the restore (so every Replace is reversible), and the restored state is **also** snapshotted right after — so you can return to that exact moment later. | ## Restore options Every version row has a **Restore** button that opens a dialog with two choices: - **Replace this app/agent** — overwrites the current state. A pre-restore snapshot is saved first. - **Duplicate from this version** — clones the chosen version into a new app or agent. The current one is untouched. Owners (and platform Admins) can use Replace. Anyone with **Design**-level access or higher can browse history and use Duplicate. ## What's included in a snapshot **Apps:** properties (name, slug, description, categories, form factor, safe mode, enabled flag), all files, and integration points. **Sharing, deployments, conversations and statistics are not included** — restoring never affects who can see your app or where it's deployed. A small **thumbnail of the app's home screen** is also captured at the end of every AI build turn and shown next to each version in the timeline (and as the app's tile thumbnail), so you can recognise versions visually. **Agents:** all configuration (name, instructions, capabilities, icon, greeting, reasoning level, MCP servers, identifier, base agent) and the agent's optimization data. **Sharing is not included.** ## Labels and retention - Versions you give a label are kept forever. - Unlabeled versions are auto-pruned: only the **50 most recent unlabeled** versions per app/agent are kept. - Click the pencil next to a version to add or change its label at any time. - Each AI-turn version also shows a short preview of **your prompt** (the user message that triggered the turn), trimmed to 140 characters — so you can recognise versions by what you asked for, not by what the AI replied. ## Where to find it - **App Builder** → **Properties** tab → *Version history* card. - **Agent Builder** → top right of the panel → **History** button. --- # Build Pro Apps Pro apps include a managed backend that is hosted by Operator. Over time this backend will provide persistent storage, secrets, server procedures, an HTTP proxy, structured logging, public access, and custom domains. ## What makes an app Pro A Pro app is an app whose owner has upgraded it from the Free tier. Pro apps consume AI credits — starting at 1 credit per day and increasing with usage. To upgrade an app: 1. Open the app in the App Builder. 2. Switch to the **Properties** tab. 3. In the **Pro App** card, click **Upgrade to Pro**. Downgrading returns the app to the Free tier. Managed backend features stop being available, and the app stops consuming backend credits. ## Cloud tab Once an app is Pro, a **Cloud** tab appears in the App Builder. Operator Cloud provides managed services that apps can use without you having to host or maintain a separate backend. Its **Overview** shows which billable mechanisms are enabled and estimates their daily and 30-day cost. Cloud billing is not enforced during the BETA period. When billing begins, a Pro app will use 1 Operator Credit per day for Cloud access, plus 1 credit per day for each enabled mechanism: **Files**, **Tables**, **Secrets**, **Web Requests**, **Triggers** and **Procedures**. Each Trigger or Procedure call will use another 0.1 credit. Call charges vary with actual use, so they are shown separately from the fixed estimate. The Cloud tab also contains **Pages** and **Cache**. These support the app but are not counted as separate daily mechanisms in the Overview. ## Files The Files section lets you store files that the app can read — and, if you allow it, write — while it runs. Useful for configuration, templates, reference data, or generated reports. - Up to 500 files per app. - Up to 5 MB per file. - Up to 100 MB total storage per app. Any file can be marked **read-only**, so the app can read it but never overwrite or delete it. By default an app can only read and overwrite files that already exist; you can also allow it to create new files while it runs. Files are private to each app. See [File Storage](pro-apps-files) for the full details. ## Tables The Tables section gives the app its own records — orders, settings, drafts, favourites. Rows are found by a row key, can be grouped for listing and reporting, and are kept separately for each ERP.net instance (or shared, for global tables). - Up to 10 KB of data per row. - Up to 100 000 rows per table. - Up to 200 000 rows per app. Just tell the App Builder what the app should remember — *"keep a list of the daily requests"*, *"remember my last selection"* — and it creates the tables and wires them into the app. See [Table Storage](pro-apps-tables) for the data model and how the app uses it. ## Secrets The Secrets section stores credentials — API keys, client ids and secrets — that the app can use but never see. Values are write-only: they can be set and replaced, never read back. Each secret can hold one global value for the app plus a separate value for a specific ERP.net instance, which takes precedence when the app runs there. See [Secrets](pro-apps-secrets). ## Web Requests The Web Requests section defines outbound calls to external services. The app calls a request by name and passes parameters; the address, headers, body and credentials stay on the backend. Bearer, basic and OAuth2 client-credentials authentication are supported, with tokens fetched and renewed automatically. See [Web Requests](pro-apps-requests). ## Pages The Pages section defines additional URL paths for the app beyond the home page. Each page has its own source folder and access mode — public, signed-in Operator user, or signed-in ERP.net internal user. Use pages for separate screens, public landing pages, and shareable forms. Each page lives in its own folder under `pages/`; sub-pages are nested sub-folders. See [Pages](pro-apps-pages). ## Procedures and Cache The Procedures section holds small pieces of server-side code the app calls when it needs something the browser must not do, such as signing in to another service with a password, using a secret, or combining several calls. The Cache section shows what those procedures keep for a short time (usually sign-in tokens), without revealing the contents. Not sure whether an app needs a Web Request or a procedure? Start with a Web Request; see [Web Requests or Procedures?](pro-apps-procedures#web-requests-or-procedures). See [Procedures](pro-apps-procedures). ## Who the app sees as the current user An app can ask Operator who is using it. It always gets your **Operator account**, and — when available — the **ERP.net user** of the instance the app runs on. The ERP.net user is reported only when the signed-in session belongs to that same instance. If you switched instances, or the loaded session comes from another connection (including a client-mode one), the app gets no ERP.net user rather than a name from a different instance. Apps then fall back to your Operator name. This keeps authorship stamped on saved records consistent with the instance the record is stored in. ## Coming soon The managed backend will expand to include: - **Logging** — persistent, queryable app logs with retention and quotas. - **Public Access** — expose selected backend endpoints publicly. - **Custom Domains** — serve apps and backend APIs from your own domain. --- # Pro App File Storage Pro apps can store and retrieve files through the managed backend. This page explains how to configure file storage and use it from an app. ## Stored files vs. source files An app has two very different kinds of files: | | **Source files** | **Stored files** | |---|---|---| | What they are | The app's own program code | Documents and data used by the app — spreadsheets, text files, configuration, reference lists | | Where you find them | **Code** tab | **Cloud → Files** (Pro apps only) | | Who changes them | The App Builder, when you ask for a change to the app | You, by uploading and deleting files — and the app itself while it runs, if allowed | When you talk to the App Builder about a file by its name — for example "show the contents of *Product Taxonomy (SMB).txt* in a tree" — it means a **stored file**. The App Builder can list stored files, read them to learn their format, and build the app so it loads them while it runs. It will ask you which kind you mean if the name is ambiguous. Examples of things you can ask the App Builder: ```text Add a page that shows the rows of prices.csv grouped by product group. Read taxonomy.txt and build a collapsible tree from it. Which stored files does this app use? Mark settings.json as read-only so the app cannot overwrite it. ``` ## Enabling file storage File storage is available only for Pro apps. To enable it: 1. Open the app in the App Builder. 2. Switch to the **Cloud** tab. 3. Select **Files** from the left menu. 4. Turn on **Stored Files**. Once enabled, the App Builder can upload files and the app can use them while it runs. You can also simply ask the App Builder to do it for you, for example: > Enable stored files for this app and let it create new files at runtime. The App Builder changes both settings itself (the app must already be Pro) and confirms what is now on. ## File storages and who sees which files Files live in **named storages**. Each storage decides who its files belong to, and this is chosen once, when the storage is created: | Scope | Who sees the files | Typical use | |---|---|---| | **Global** | Everyone using the app | Reference data shared by all customers — taxonomies, price lists, templates | | **Per instance** | Only users with a regular (internal) connection to that ERP.net instance | Customer documents that must never be seen by another company — CVs, contracts, scans | | **Per user** | Only the person who created them | Personal drafts and scratch files | The scope is shown as a badge next to each storage in **Cloud → Files**, and the file list shows which instance or user every file belongs to. An app running in one instance simply never sees the files of another one — nothing needs to be filtered in the app itself. Isolation is enforced by the platform, not by the app. Files of a per-instance storage are only served to people who are actually signed in to that instance as an internal user; a client-mode (self-service customer) connection never unlocks them. Files of a per-user storage are only served to their owner. App designers keep full visibility of every instance and user, so they can manage the content in **Cloud → Files**. Examples of what you can ask the App Builder: ```text Create a per-instance file storage called "cvs" and keep candidate CVs there. Which file storages does this app have, and what is their scope? Move the taxonomy file into a global storage so every customer gets it. ``` ## Uploading and downloading files In the **Files** section, pick a storage, click **Upload File** and choose one or more files from your computer. When the storage is per instance, the files are uploaded into the instance currently selected in the top bar; when it is per user, they belong to you. Files larger than 5 MB are rejected, and uploads stop once an app reaches 500 files or 100 MB in total. To get a stored file back, open the row menu (⋯) and choose **Download**. The App Builder can also mark a file as **read-only**. Read-only files cannot be changed or deleted by the app while it runs. They are useful for configuration files, templates, and reference data. ## Moving files between storages Files are not stuck where they were first uploaded. Ask the App Builder to move one, and it keeps the content, the file type and the read-only flag — so PDFs, images and other binary files survive the move intact. It can also rename the file on the way. ```text Move taxonomy.txt from the default storage into the "reference" storage. The CVs are in the global storage — move them into the per-instance "cvs" storage. Rename prices.csv to price-list-2026.csv while moving it to "reference". ``` A few rules keep the move safe: - Moving between two storages with the same scope keeps the file's instance or owner — it never changes hands. - Moving a file from a global storage into a per-instance one puts it into the instance currently selected in the top bar, unless you name another one. The App Builder always says which instance it used. - Moving a customer-specific file into a global storage makes it visible to everyone using the app; the App Builder warns you before doing it. - A move never overwrites an existing file, and read-only files must have the flag cleared first. - When the same file name exists in several instances, they are moved one instance at a time so nothing collides. ## File name rules File names must use Latin letters, digits, spaces, and basic punctuation. Names with Cyrillic or other non-Latin letters, accented characters, or emoji are rejected — rename the file and upload it again. - Allowed: letters, digits, spaces, and `. - _ ( ) [ ] & + , @ ' !` - Not allowed: `\ / ? # % * : | " < >` - The name must not start or end with a space or a dot, must not contain `..`, and must have an extension - Up to 120 characters Examples: ```text Valid: Product Taxonomy (SMB).txt Valid: report_2026-08.csv Invalid: Product Тaxonomy.txt (Cyrillic "Т") Invalid: report:final.csv (colon) ``` ## Limits | Limit | Value | |-------|-------| | Max files | 500 | | Max file size | 5 MB | | Max total storage | 100 MB | The usage meters at the top of the Files section show the current usage against each limit. ## What an app is allowed to do By default, an app can only read and overwrite files that already exist. It cannot create new files. To let the app create new files while it runs, turn on **Allow app to create files at runtime** in the Files section — or ask the App Builder to turn it on. An app is stopped with a clear message when it tries to do something it is not allowed to do — for example creating a file when runtime creation is off, or changing a read-only file. If you see such a message, adjust the setting in the Files section or ask the App Builder to explain what the app was trying to do. ## Showing PDFs inside an app Apps run in a protected frame, and Chrome does not allow its built-in PDF viewer to run there. If an app tries to show a PDF the usual way, Chrome replaces it with a grey **"This page has been blocked by Chrome"** box. The file is intact — only the browser's viewer is blocked. The way around it is to let the app draw the PDF itself, page by page. Ask the App Builder for something like: ```text Show the attached CV as a real PDF preview inside the dialog, drawn by the app (not an embedded viewer), with page navigation and a fit-to-width view. ``` Keep the **Open / Download** button next to the preview as well: opening the PDF in a new tab always works, because a new tab is not inside the protected frame. ## Security Files are isolated per app. One app cannot access files stored by another app. Files are stored in Operator's managed storage and are not directly reachable from the public internet unless a future public-access feature is enabled. --- # Pro App Table Storage Pro apps can keep their own records in the managed backend — orders, settings, favourites, drafts, checklists, anything that does not belong in ERP.net and is not a document. This page explains the data model, the limits, and how you work with tables. ## When to use tables | Need | Use | |---|---| | Business data that belongs to the ERP system | ERP.net entities | | A document, spreadsheet or reference list you upload | [Stored files](pro-apps-files) | | Records the app itself creates and updates | **Tables** | If you ask an app to "remember my last selection", "keep a list of requests", or "save this form for later", tables are the right place. ## Data model A table is a container of rows; each row holds one record. - **Table** — a named container that belongs to one app. It is either **per instance** (each ERP.net instance the app runs against keeps its own rows) or **global** (one shared set of rows for the whole app). - **Row key** — identifies the row. It is enough on its own: give the app a row key and it finds the row directly. Usually generated by the app rather than taken from the record's content. - **Group key** — optional grouping value, such as a month, a category, or a customer. Used to list related rows together. - **Name** — an optional display value that is searchable. - **Data** — the content of the row. How you choose keys decides how fast the app is: | Lookup | Speed | |---|---| | By row key | instant | | By group key, or a range inside a group | fast, indexed | | By name (starts with, or contains) | fast, indexed | | By created, changed or business date | fast, indexed | | By any other value inside the row | slower — the whole group is scanned | ## What every row records automatically Beyond what you store, each row keeps its own history: - **Created** — when the row first appeared, and **who** created it (empty when the app or a background process created it). - **Changed** — when the row was last written, and **who** changed it. Both dates are indexed, so questions like "everything added this week" or "the twenty most recently changed records" answer instantly, no matter how big the table is. ## The business date Many records have one date that the business actually cares about — the document date, the activity date, the due date, the effective date. That is different from when the row happened to be typed in. Each table can switch on a single **business date** and give it a name. When it is on, every row can carry that date, it is indexed, and filtering or sorting by it is fast. Rows that leave it empty cost nothing. Turn it on when creating the table in **Cloud → Tables** (or ask the App Builder), name it after what it means, and the column appears in the row list. ```text Add a business date called "Document date" to the invoices table. Show the invoices with a document date in July, newest first. List the requests created in the last 7 days. ``` Use it instead of keeping that date inside the row content — a date buried in the content cannot be searched quickly. ## Designing your tables ### Your ERP.net data comes first When your app runs against a connected ERP.net instance, the ERP.net schema takes precedence. The App Builder checks the ERP.net entities and your custom attributes before it proposes any table, and it stores business data — orders, partners, products, documents — where it belongs: in ERP.net. Tables are used for what ERP.net does not model, for example saved filters and layouts, drafts that are not posted yet, app-specific lists and mappings, or records the app keeps for itself. A table may point at an ERP.net record, but it never becomes a second copy of it. If your app is standalone, with no instance connected, there is nothing to defer to — the App Builder designs the tables freely and they act as the app's own database. The four elements above are not interchangeable — how you assign them decides how fast the app feels. When you ask for storage, the App Builder proposes a design first and asks you to confirm it. - **Row key** — the address of the row, not one of its values. By default the app generates it automatically: a row keeps the same key forever, and a key taken from something that can later change (a name, a code, an e-mail) causes duplicates. A real-world identifier is used as the key only when it truly never changes — a setting name, an ERP.net record, a user, or a calendar day. Both are equally fast. - **Group key** — pick whatever one screen shows at a time: a month, a category, a customer, a status. Rows that are listed together should share a group key. - **Name** — write the label you would want to see in a list: "Acme Ltd — 1 240 BGN" rather than an internal code. This is also what searches match. - **Data** — everything else. Values kept only in the data are fine to read and display, but slow to filter by, so anything you filter or sort by on a regular screen is better placed in the group key or the name. A worked example — daily requests: ```text Table: requests (per instance) Row key: generated automatically the row's permanent address Group key: 2026-08 the month the list screen shows Name: Acme Ltd - 3 pallets what appears in the list Data: request number, customer, quantity, status, notes, delivery address ``` The request number lives in the data, where it can be corrected. If instead the app stored one row per ERP.net partner, the partner's id would be the natural row key — it never changes, and the app can write the row without looking it up first. The App Builder also keeps a written schema of every table it creates — the meaning of the keys and the fields expected inside the data — so later conversations pick up exactly where the previous one left off. ## Enabling table storage Table storage is available only for Pro apps. 1. Open the app in the App Builder. 2. Switch to the **Cloud** tab. 3. Select **Tables** from the left menu. 4. Turn on **Tables**. Or simply ask the App Builder: > Enable tables for this app and create a table for the daily requests. The App Builder turns the setting on itself (the app must already be Pro), creates the tables, and can fill them with reference data. ## Read-only tables Any table can be marked **read-only**. The running app can still read it, but only you and the App Builder can change its rows. This is useful for reference data such as price lists, statuses, or configuration. ## Active and inactive rows Every row has an **Active** value, switched on when the row is created. Switching a row off keeps it — with its full history — but takes it out of circulation: lists, searches and counts in the app return active rows only. This is the right way to retire a price, a status or an old request without deleting anything. Finding the active rows stays fast no matter how many retired ones pile up. Inactive rows are still reachable when they are asked for explicitly: the app can request them, and looking a row up directly by its row key always finds it, active or not. In **Cloud → Tables** each row shows an Active switch you can flip, and a **Show inactive** toggle above the list reveals the retired rows. Things you can ask the App Builder: ```text Mark the discontinued statuses as inactive instead of deleting them. Show me the inactive rows in the price list. When an order is cancelled, deactivate its row instead of removing it. ``` ## Letting the app create tables By default the app can only use tables that already exist. Turn on **Allow the app to create new tables at runtime** when the app genuinely needs to create containers on the fly. ## Browsing tables The **Cloud → Tables** section shows every table of the app with its scope, read-only badge, row count and stored size. Selecting a table lists its rows — group key, row key and name — with a search box, and clicking a row opens its full content. ## What you can ask the App Builder ```text Keep the submitted requests in a table, grouped by month. Remember the last filter each user selected. Create a table with the delivery statuses and mark it read-only. Show me the rows added this month for customer Acme. ``` ## Limits - Up to 10 KB of data per row. - Up to 100 000 rows per table. - Up to 200 000 rows per app across all instances. Rows are private to the app, and an app connected to one ERP.net instance never sees the rows of another — unless the table is global. --- # Pro App Secrets Pro apps often need credentials — an API key, a client id and secret, a token for another system. Secrets let you store those credentials in the managed backend, where the app can *use* them but never *see* them. A secret is **write-only**: you can set it and replace it, but nobody can read it back — not you, not the App Builder, and not the running app. The interface only ever shows the name and an optional description — no part of the value is ever displayed, not even masked. ## When to use secrets | Need | Use | |---|---| | A password or key for an external service | **Secrets** | | Data the app creates and reads | [Table storage](pro-apps-tables) | | A document or reference list | [File storage](pro-apps-files) | Secrets are never used on their own — they are referenced by a [web request](pro-apps-requests), which runs on the backend and attaches the credential there. A secret belongs to the app as a whole; it does not depend on which ERP.net instance you are working with. ## Enabling secrets 1. Open the app in the App Builder. 2. Switch to the **Cloud** tab. 3. Select **Secrets** from the left menu. 4. Turn on the section. Secrets require a Pro app, and only users with **Design** access to the app can manage them. ## Adding a secret Click **Add secret**, then give it: - a **name** — starts with a letter, contains letters, digits and underscores, for example `ACME_CLIENT_SECRET`; - an optional **description** — what the credential is for and where it came from; - the **value** — stored encrypted immediately and never shown again. To change a credential later, use **Replace** and type the new value. There is no way to reveal the old one. Limits: up to 25 secret names per app, up to 4 KB per value. ## A secret is not tied to an ERP.net instance A secret is simply a name and a value belonging to the app. There is no per-instance variant, and nothing changes when you switch the instance in the top bar. When a [web request](pro-apps-requests) needs to talk to a particular ERP.net instance, that instance is **fixed inside the request**: its address is part of the request's URL and its credentials are the request's own secrets. If the same integration must reach two different instances, define two requests with their own secret names, for example: ```text CATALOG_DEMO_CLIENT_ID → used by the request "catalog.demo.products" CATALOG_DEMO_CLIENT_SECRET CATALOG_LIVE_CLIENT_ID → used by the request "catalog.live.products" CATALOG_LIVE_CLIENT_SECRET ``` This keeps the behaviour predictable: a request always calls the same destination with the same credentials, no matter who runs the app or what they have selected. ## What the App Builder can and cannot do You can ask the App Builder to prepare the credentials an integration needs: ```text This app will call the Acme API. Declare the secrets it needs. Which secrets does this app already have? ``` When a credential is missing, the App Builder picks a clear name itself (for example `ACME_CLIENT_SECRET`) and opens the secret form for you, with the name and a short description already filled in. All you do is paste the value and save. If two credentials are needed — an id and a secret — it asks for them one after the other. The App Builder can see secret **names** and tell you which ones are still empty, but it can never read or set a value. The value goes straight from your clipboard into encrypted storage. ## How secrets stay safe - Values are encrypted before they are stored and can only be decrypted by the backend while a request runs. - Nothing in the browser, the app code, or the App Builder conversation ever receives a value. - Test results and logs redact credentials and authorization headers. --- # Pro App Web Requests Web requests let a Pro app talk to external services — a courier API, a payment provider, a partner system — without ever holding the credentials or even knowing the address it calls. You define the request once, in the backend. The running app calls it **by name** and passes a few parameters. Everything else — the address, the headers, the body, the credentials — stays on the server. ## How it works ```text App → "call acme.getOrder with orderId = SO-1042" ↓ (backend adds address, headers, credentials) https://api.acme.com/v2/orders/SO-1042 ↓ App ← the response ``` The app cannot change where the call goes. Parameters can only fill in the places you allowed, so a request can never be pointed at a different service. ## When a Web Request is not enough A web request makes **one** call with standard sign-in: none, a stored key, or a standard company sign-in. When a service needs a custom login flow, a remembered token, signed requests, or several calls combined, the app needs a [Procedure](/help/pro-apps-procedures) instead. Web requests are included in the daily Cloud cost; each procedure run costs 0.1 credit after BETA. See [Web Requests or Procedures?](/help/pro-apps-procedures#web-requests-or-procedures). ## Enabling web requests 1. Open the app in the App Builder. 2. Switch to the **Cloud** tab. 3. Select **Web Requests** from the left menu. 4. Turn on the section. Web requests require a Pro app. Only users with **Design** access can define or change them; anyone who can run the app can call an enabled request. ## Defining a request Click **Add request** and fill in: - **Name** — how the app refers to it, for example `acme.getOrder`. - **Title and description** — what it does, in plain words. - **Method** — `GET`, `POST`, `PUT`, `PATCH` or `DELETE`. - **Address** — the target address, with placeholders where parameters go, for example `https://api.acme.com/v2/orders/{{param.orderId}}`. - **Parameters** — the values the app is allowed to supply: name, type, whether they are required, and an optional default. - **Headers** and **body template** — fixed values, with the same placeholders available. - **Authentication** — see below. - **Enabled** — turn a request off without deleting it. Press **Test** to run the request from the backend and see the response with all credentials redacted. ## Authentication Credentials always come from [secrets](pro-apps-secrets) — you reference the secret by name, never by value. | Option | What it does | |---|---| | **None** | The service needs no credentials. | | **Bearer token from a secret** | Sends a bearer token taken from a secret. | | **Basic auth from secrets** | Sends a user name and password taken from two secrets. | | **OAuth2 client credentials** | The backend logs in with a client id and secret, gets an access token, and uses it. | With OAuth2 client credentials the backend handles the whole login for you: it fetches the token, keeps it until shortly before it expires, reuses it for every call, and renews it automatically. Tokens are kept separately for each set of credentials, so two requests with different credentials never share a token. ## Using it in an app Just describe what the app should do — the App Builder wires the call in for you: ```text When the user picks an order, fetch it from Acme and show the delivery status. Add a button that pushes the selected document to the partner system. Which web requests can this app call? ``` The app receives the status code and the response content. If the request is disabled, a parameter is missing, a secret has no value, or the external service fails, the app gets a clear message explaining what went wrong. ### What the app gets back A call always returns a small wrapper around the answer — the status of the call plus the content: ```text { status: 200, data: } ``` The answer itself is always under `data`. For an ERP.net list that means the rows are `result.data.value`. If anything goes wrong, the call fails with a readable message instead of returning an error object, so app code wraps it in a try/catch. ```js try { const res = await operator.requests.call('catalog.products', { top: 60 }); const payload = res.data ?? res; // tolerant unwrapping const rows = Array.isArray(payload.value) ? payload.value : []; } catch (err) { showError(err.message); } ``` The **Test** button in the backend shows the same content: what appears under `data` there is exactly what the running app receives. The App Builder can create, change, test, mark public and delete these requests for you — you only need to enter the credential values yourself under [Secrets](pro-apps-secrets). ## Public requests (for public pages) A visitor of a [public page](pro-apps-pages) is not signed in, so the app cannot use that visitor's ERP.net connection, backend tables, stored files or secret values. The supported way to show server data on a public page is a request marked **Public**. A public request: - can be called by anyone visiting a published public page of the app; - runs entirely on the server with **its own stored credentials** — typically a service account or client id / secret; - never receives the visitor's identity, and never exposes the credentials to the browser. This also covers ERP.net: point the request at the ERP.net Domain API address, give it a service login stored in secrets, and the public page can show the data without anyone signing in. Example — a public product catalog: ```text Address: https:///api/domain/odata/General_Products_Products?$filter=Active eq true and ShowInCatalog eq true&$top={{param.top}} Auth: OAuth2 client credentials (client id and secret from Secrets) Public: yes ``` Keep public requests as narrow as possible: bake the filters into the address and expose only harmless parameters such as paging or a search term. Anyone with the link can call a public request. ## Safety limits - Only `https` addresses; internal and local network addresses are refused. - Redirects to another host are not followed. - Response size and duration are capped, so a slow service cannot block the app. - Sensitive response headers never reach the app. - Per-app and per-user rate limits apply. - Logs record which request ran and which credential scope was used — never the credential itself. --- # Pro App Pages *Add extra URL paths and public pages to Pro apps* Every Operator App has a **Home** page served by `index.html` at the root path `/`. Pro apps can define additional pages, each with its own URL path and access mode. ## When to create a page A **Page** is a distinct navigable destination in the application. Do not create a new Page merely because the UI shows different content. Create a new Page when one or more of these apply: - The user explicitly asks for a page, URL, route, or independently accessible destination. - The destination should have its own stable/deep-linkable URL. - It has a different Page Access Mode. - It is a major top-level or hierarchical navigation destination, such as `/pricing`, `/docs`, or `/account/orders`. - It should be independently refreshable/bookmarkable and browser Back/Forward navigation should naturally move between it and other pages. - It needs page-specific browser metadata or hosting behavior, such as title, SEO, Open Graph metadata, or public indexing. Do not create a new Page merely for: - dialogs, popovers, drawers, or modal editors; - tabs within the same logical destination; - filters, sorting, pagination, or selected records; - expandable sections; - wizard steps that belong to one continuous operation; - alternate views of the same workspace where a separate URL is not useful; - temporary UI state. When uncertain, prefer keeping related functionality within the existing Page. Create another Page only when it represents a meaningful independent destination. ## Why use pages? - **Separate URLs** for distinct screens — for example `/dashboard`, `/settings`, or `/report`. - **Public landing pages** — share a form or a dashboard with people who do not have an Operator account. - **ERP.net internal pages** — screens that only make sense when the visitor is connected to an ERP.net instance as an internal user. ## How pages work Pages are managed under **Cloud → Pages** in the App Builder workspace. - Each page is represented by a source file at `pages//index.html`. - The page's CSS and JavaScript files live in the **same folder** — the folder-per-page rule is strict. - Sub-pages are nested folders: `pages/parent/child/index.html` is served at `/parent/child`. - The path shown to users and the file path must match. If you move or rename a page, update both the folder and the page record. - Home is always `index.html` at `/`. Do not create a page record for it and do not delete it. - Links between pages can carry details after a `?`. Example: a shop catalog links each product to `product?id=…`, and the product page reads the `id` to show the right item. The details are kept when the visitor clicks the link. ## App access mode (the Home page) The app itself has an **access mode** that controls who can open the Home page — and it is the **default access mode for every new page** you create. You set it when the app is created, and you can change it later under **Cloud → Pages** (the Home row). Defaults for new apps: - **ERP.net Internal User** when an ERP.net instance is connected — the typical case for an "ERP data app". - **Operator User** when no instance is connected — the app still requires sign-in. Choose **Public** only when people without an account genuinely need to open the app — for example a landing page, a public form, or a shareable dashboard. Public mode requires a **Pro** app. When the Home page is public, the app's address is `https://app.operator.net/p/` and the app is listed to crawlers accordingly. **The address to share.** A public-home app has no instance in its address. Share `https://app.operator.net/p/` (add `/` for a sub-page); you will also find it under **Cloud → Pages** and in the **Deploy** tab, and the maximize button in the app header opens it. If someone opens the signed-in style address `/a//`, the trailing part is read as a page path and served publicly — no login prompt. Access is always decided per page: a public page opens for everyone, while a page that requires an Operator or ERP.net user still asks for sign-in, even in the same app. > A public Home page also makes the app's *public* backend requests callable without sign-in — mark only the requests that are safe to expose as **Public**. ## Access modes | Mode | Who can open it | Typical use | |------|-----------------|-------------| | **Public** | Anyone with the URL; no sign-in required | Landing pages, public forms, shareable dashboards | | **Operator User** | Signed-in Operator users | Internal tools and team screens | | **ERP.net Internal User** | Signed-in Operator users with an active ERP.net internal connection | Screens that call ERP.net data directly | Public pages are Pro-only. They are served from `/p//`. A page with no explicit access mode inherits the app's access mode. ## Public backend requests A public page has no signed-in visitor, so it cannot use your ERP.net connection, the app's tables, stored files or secret values. Anything it shows from a server must go through an app [web request](pro-apps-requests) marked **Public**. A public request runs on the server with its own stored credentials, so it can read ERP.net data (via a service login) or any external API without the visitor signing in. The App Builder creates and marks these requests for you — you only enter the credential values under [Secrets](pro-apps-secrets). ## Building pages Describe the new page to the App Builder in chat. For example: > "Add a public landing page at `/register` with a simple contact form." The App Builder will: 1. Create the page record under **Cloud → Pages**. 2. Write the source files under `pages/register/`. 3. Update any navigation in the app so users can reach the new page. Use the **Design** tab to preview the page, and **Code** to inspect or edit the generated source. --- # React to Schedules and Events Most apps only do something while somebody is looking at them. A **trigger** lets an app act on its own: every morning at eight, when an email arrives, when a record changes in your ERP.net instance. You describe what should happen in plain words — the App Builder sets everything up. A trigger is not an AI run: it does exactly what it was told, every time, and it costs no AI credits. ## How it works Something happens — a set time arrives, an email comes in, a record changes — and your app's trigger starts. It can refresh the app's tables, read or update data in your ERP.net instance, prepare a PDF report, and send emails or notifications. Nobody needs to have the app open. ## Adding a trigger Just say what should happen, in plain words: ```text Every weekday at 07:30, refresh the "open orders" table from ERP.net. ``` ```text When an email arrives in the support mailbox, add a row to the "inbox" table with the sender, the subject and the date. ``` ```text When a webhook is called, look up the order and mark it as shipped. ``` The builder sets up the trigger and tells you where it lives. ### More things to ask for Scheduled work: ```text Every night at 23:00, write today's total stock quantity into the "daily stock snapshots" table. ``` ```text Every Monday at 08:00, email last week's sales summary as a PDF to sales@company.com. ``` ```text On the first day of each month at 06:00, recalculate the customer balances and store them in the app. ``` Reacting to things that happen: ```text When a webhook is called with a tracking number, mark the matching order as shipped and notify me. ``` ```text When an email arrives in the orders mailbox, save the sender, subject and date, so the app can show unprocessed orders. ``` Small adjustments later: ```text Pause the nightly stock trigger until next week. ``` ```text Rename the trigger to "Morning orders refresh" and move it to 06:45. ``` Each of these is one sentence to the builder — and the trigger appears in the Triggers tab. ### Changing only when a trigger runs To move a scheduled trigger, just say the new time. The builder changes only the schedule — the script, the instance it is tied to, and its other settings stay exactly as they were. ```text Move the daily stock snapshot to 07:30. ``` ```text Run the order sync every 30 minutes instead of once a day. ``` When the trigger's name mentions the time, the builder updates the name too. You can also just rename a trigger: ```text Rename the trigger to "Daily stock snapshot at 19:00" and move it to 19:00. ``` The Triggers tab shows each scheduled trigger's next run in its own timezone, or "paused" while it is switched off. Switching a trigger back on needs nothing else; it runs at its next scheduled time. ## Watching them run Open the app in the App Builder, go to the **Cloud** tab and choose **Triggers**. For each trigger you see: - when it will run next, and when it last ran, - whether each run succeeded, how long it took, and anything that went wrong, - a switch to pause it and a button to delete it. Runs are kept for 30 days. ## What a trigger can do - refresh the app's **tables**, so the app shows fresh data next time somebody opens it; - read and write data in your **ERP.net instance**, even while nobody is connected; - prepare a **PDF report** from a simple page layout and send it by **email**; - send a **notification** to you when something needs attention; - use what started it — the email content, the changed record, the time it ran. ## PDF reports by email The most common use of a trigger: prepare a document on a schedule and email it. Just ask: ```text Every working day at 07:00, make a PDF with the current stock by product and email it to warehouse@company.com. ``` ```text Every Monday, email last week's sales by customer as a PDF to me and the sales manager. ``` What to expect: - **The PDF** has headings, paragraphs, lists and tables. Long tables continue on the next page with the column headers repeated. Bulgarian and other Cyrillic text works. Pictures and custom fonts are not included. - **A copy is kept** in the app's files, so you can open earlier reports later. - **The email** comes from the Operator no-reply address. Up to 10 recipients per email, 20 emails per run and 200 per app per day. - **If sending fails** (a wrong address, the daily limit), the run is marked as failed with the reason, and you can see it in the Triggers tab. These emails are for reports and notices tied to your business, not for newsletters or mailing lists. ## Separate data for each ERP.net instance Some apps keep the same kind of data separately for each instance — for example, one row of daily stock figures per instance. When the builder creates a trigger for such data, it ties the trigger to the instance you are working with. From then on, the trigger reads and writes exactly that instance's data, even though nobody has the app open. The Triggers tab shows each trigger's instance, or "all instances" when it has none. ## Live refresh If the app happens to be open while a trigger updates its data, the page refreshes itself straight away — no manual reload needed. ## Good to know - Triggers need a **Pro app** and **Design** access. - The whole section has its own on/off switch at the top of Cloud → Triggers — switch it off to pause every trigger of the app at once; each trigger still keeps its own switch. - A paused trigger keeps its history; a deleted one removes the schedule it created. - Failures are recorded, not retried — check the runs list when something looks stale. - If the work needs judgement rather than a fixed recipe, use an [automation](automations) with an agent instead. --- # Procedures Some things an app must never do in the browser: sign in to another company's service with a password, use a secret key, or keep a login token. A **backend procedure** is a small piece of code that runs on Operator's servers instead. The app asks it for a result and gets only that result back. Passwords, tokens and the other service's raw responses stay on the server. Procedures are available in [Pro apps](/help/pro-apps). You describe what you need in plain words, and the App Builder writes, tests and connects the procedure. ## When you need one - **Another service has its own way of signing in.** For example, an address database that wants a user name and password and then hands out a short-lived token. - **A calculation or check uses a secret.** The browser must never see that secret. - **Several calls need to be combined.** For example: look something up in one system, check it against another, and return one clean answer. For work that must happen while nobody has the app open, use [triggers](/help/pro-apps-triggers). ## Web Requests or Procedures? Both keep credentials on the server. The difference is how much they can do, and what they cost. | | Web Requests | Procedures | |---|---|---| | What it does | One call to one service | Any secure logic: several calls, custom sign-in, checks with a secret | | Sign-in it handles | None, a stored key, or a standard company sign-in | Any, including non-standard logins and signed requests | | Remembers a login token | No | Yes, for up to 24 hours | | Code | None — just settings | A small script the App Builder writes | | Cost (after BETA) | Included in the daily Cloud cost | Daily cost plus 0.1 credit per run | **Rule of thumb:** start with a Web Request. Use a procedure only when a single standard call is not enough. Examples: - *"Show today's exchange rates from a public rates service."* → **Web Request** — one call, no sign-in. - *"Look up a parcel's status with our courier, using our API key."* → **Web Request** — one call, a stored key. - *"Sign in to our courier with its custom login, keep the token, then book a shipment."* → **Procedure** — non-standard login and several steps. - *"Check the customer with our credit agency and show only the rating."* → **Procedure** if the agency needs signed requests or a login step; otherwise a Web Request is enough. The App Builder follows the same rule and tells you when it chooses a procedure. ## Asking for a procedure ```text Our address provider DataMap signs in with a user name and password and returns a token. Let the app search addresses as the user types, and keep the token so we don't sign in on every search. ``` ```text When the user presses "Check credit", ask our credit agency's service about this customer and show only the rating and the limit. ``` ```text Add a "Validate VAT number" button that checks the number with the EU service and fills in the company name. ``` When the service needs credentials, the builder asks for them first. They are saved as [Secrets](/help/pro-apps-secrets), and you type them into a secure form. They never appear in the conversation or in the app. ## What you see in Cloud → Procedures - **The list of procedures.** Each one shows what it does, who may use it, and its last result. - **An on/off switch.** A switched-off procedure cannot be called by the app. - **View script.** Shows the code, for anyone curious or reviewing. - **Test.** Runs the procedure once with sample input and shows the answer and any messages. - **Recent runs.** Shows each run with its time, how long it took, and any error. ## Who may use a procedure A procedure can be open to **everyone who can run the app**, or only to **the people who design it**. The second option suits admin tools. When a procedure reads ERP.net data, it does so as the person using the app, on the instance they are working in. ## Cache Procedures and triggers can remember small things for a limited time. This is usually the sign-in token of another service, so the app doesn't sign in again on every click. Each item expires on its own, after at most 24 hours. **Cloud → Cache** lists what is currently remembered. For each item you see its name, whether it belongs to one instance or all of them, its size, and when it expires. The contents are never shown, because they are often tokens. Press **Clear** on an item, or **Clear all**, to make the app sign in fresh on its next call. This is useful after you change a password. ## Good to know - The whole section has its own on/off switch at the top of Cloud → Procedures — switch it off to stop the app calling any procedure; each procedure still keeps its own switch. - A procedure must finish within 15 seconds. - It can call outside services only over secure (https) addresses. Internal network addresses are blocked. - Procedures use the same simple script engine as triggers. The builder knows its limits. - Run history is kept for 7 days. --- # Agents *Build your own specialists on top of Operator's base agents* A user-defined agent is a saved specialist that wraps one of the platform's **base agents** with your own identity, instructions, greeting, capabilities, and (optionally) a flow diagram. Once saved, it appears in the agent selector and behaves like any built-in agent — except it follows the focus *you* gave it. ## Why build your own agents User-defined agents are useful when you want a repeatable specialist tuned to the way your business actually works. - **Capture and refine real business processes** — write instructions once, save them, and keep improving them over time instead of repeating the same guidance in every chat. - **Optimize for repeated use** — prepare the agent for a specific ERP instance so it remembers the people, products, and document types it works with, then runs faster and more reliably on every later conversation. - **Delegate to other agents** — let one saved agent hand off work to another, so complex workflows split into focused, reusable pieces. - **Visualize the workflow** — every agent gets an auto-generated diagram of its data flow, capabilities, and the entities it touches, making it easy to review and share. ## Agent or Process Every user-defined entry has a **Kind**: - **Agent** — runnable. Has capabilities, can act, shows up in selectors. - **Process** — not runnable. Captures a procedure, SOP, or diagram you want to document; hidden from selectors. You don't pick the Kind from a menu — the **Agent Builder** decides at creation time from how you describe what you want, and you can flip the Kind later from the agent's Properties. ## What you can shape on an agent Each of these is its own area you can fill in over time: | Area | What it controls | |---|---| | **Identity** | Name, identifier (for @mentions), description, icon | | **Base agent** | Which platform agent yours extends — sets available capabilities, reasoning ceiling, and instance requirements | | **Reasoning level** | How deeply the agent thinks per turn (Fast → Genius, or Auto) | | **Instructions** | Private guidance the AI sees on every turn; users don't see it | | **Greeting** | Welcome message and quick-action buttons shown when a new chat starts | | **Welcome screen** | A WYSIWYG preview of what the user sees before they type | | **Capabilities** | The tools the agent is allowed to use (data, email, calendar, sub-agents, …) | | **Diagram** | An AI-generated map of the agent's data flow and actions — see [Working with Diagrams](/help/agent-diagrams) | | **Optimization** | Per-instance warm-up that pre-resolves the names and IDs the agent uses — see [Agent Optimization](/help/agent-optimization) | | **Sharing** | Give colleagues access to use (not edit) the agent | | **Delegation** | Let the agent split work across other user-defined agents — see [Delegation & Sub-Agents](/help/agent-delegation) | ## How you build and edit them You build agents by **talking to the Agent Builder**. Open it from the agent selector, describe what you want in plain language, and it creates the agent for you. A live preview panel on the side shows the agent taking shape — instructions, greeting, welcome screen, diagram — and you can keep refining either through the conversation or by editing fields directly in the preview. There's no separate "form" to fill in upfront. The agent exists from the first creation step; everything after that is iteration. ## Where your agents show up - **Top-bar agent selector** — under *My Agents* (or *Shared with Me*), for starting a fresh chat. - **Chat input "+" menu** — under *Agent*, for deliberately changing the current conversation's agent. - **Home screen** — agent picker before you start a new conversation. - **Agents page** — a full listing with two layouts: a compact **Table view** and a visual **Gallery view** showing each agent's latest diagram as a thumbnail. ## Quick links - [Creating Agents](/help/agents-creating) — Build one from scratch with the Agent Builder - [Working with Diagrams](/help/agent-diagrams) — Visualise your agent's data flow - [Using Agents](/help/agents-using) — Selection, @mentions, conversation behavior - [Sharing Agents](/help/agents-sharing) — Give colleagues access - [Agent Optimization](/help/agent-optimization) — Faster, cheaper runs on a specific instance - [Delegation & Sub-Agents](/help/agent-delegation) — Let agents call other agents - [Building an Agent Workforce](/help/agent-workforce) — Combine optimization and delegation - [Version History & Restore](/help/version-history) — Roll back any change --- # Creating Agents *Build a new agent by talking to the Agent Builder* Agents are created and edited through a conversation with the **Agent Builder**. There's no upfront form — you describe what you want, the Builder creates it, and you keep iterating. ## Start a new agent 1. Open the **agent selector** and pick **Agent Builder**. 2. Describe the agent in plain language — what it should help with, who uses it, anything specific it should know. 3. The Builder asks for the minimum it needs (a name, a base agent, and which **Kind** if the intent is unclear) and creates the agent immediately. 4. From there, you keep talking. The Builder edits instructions, greeting, capabilities, and the welcome screen as you describe changes. A live preview panel on the side shows everything taking shape. You never have to fill in a blank form. Every field below ends up filled either by the Builder during the conversation or by you tweaking it directly in the preview. ## Agent or Process — chosen from your first request Every user-defined entry is either a runnable **Agent** or a documented-only **Process** (no Execute, no capabilities, hidden from selectors). The Builder chooses one based on how you phrase the request: - Wording like *"diagram"*, *"draw"*, *"flowchart"*, *"visualize"*, *"sketch"*, *"map out"*, *"SOP"*, *"procedure"*, *"checklist"*, *"playbook"*, *"runbook"*, *"steps to…"*, *"document how…"* → created as a **Process**. - Wording like *"assistant that…"*, *"agent that can…"*, *"bot to…"*, or any list of capabilities, integrations, or actions → created as an **Agent**. - If the intent is ambiguous, the Builder asks one short question ("Agent or Process?") before creating. You can flip the Kind later from the agent's **Properties**. Promoting a Process to an Agent then lets you pick a base agent and turn on capabilities. ## The fields you'll end up with ### Required | Field | What it is | |---|---| | **Name** | Display name shown in selectors | | **Identifier** | Unique ID used for @mentions (e.g. `sales_helper`) | | **Base agent** | The platform agent yours extends | **Identifier rules** — starts with a letter or underscore; contains only letters, numbers, underscores, or hyphens; unique across your agents. Examples: `my_helper`, `sales_q4`, `support-tier1`. **Choosing a base agent** — the base agent decides which capabilities are available, the reasoning ceiling, and whether an instance connection is required. | If you need… | Pick | |---|---| | Quick data lookups, product knowledge | **Advisor** | | Daily business operations, data management | **Business Specialist** | | Customer-facing tasks, orders | **Sales Executive** | | Complex configuration, custom logic | **System Architect** | | Direct AI with no tools | **Pure AI** | ### Optional #### Reasoning level Override the base agent's default. Available levels are capped by what the base agent supports. | Level | Best for | AI cost | |---|---|---| | **Fast** | Quick lookups, simple queries | Lowest | | **Smart** | Data analysis, business operations | Medium | | **Expert** | Multi-step problem-solving | Higher | | **Genius** | Maximum reasoning with extended thinking | Highest | Leave it on **Auto** unless the agent consistently needs more (or less) than the base agent's default. Every base agent has its own minimum, default and maximum — for example a base built for analysis won't let you drop below Smart, while a lookup-oriented base won't go above Fast. Anything outside that range is rejected. You can also handle this in chat: ask the builder *"what reasoning level is this agent using?"* and it will tell you the level it actually runs at (and whether that comes from the base default or an explicit setting). Say *"set the reasoning to expert"* to change it — if the level is outside the base agent's range, the builder explains the range and offers the closest valid option. #### Capabilities and approval modes Each capability on the **Capabilities** tab has three settings: | Mode | What it means | |---|---| | **Off** | The agent has no tools from this capability. | | **Ask** | The agent can use the tools, but every sensitive action (sending an email, creating or changing a record, changing a document state) waits for your approval in the chat. This is the default. | | **Auto** | Sensitive actions run immediately, without asking. | You can set all three by talking to the Agent Builder, for example: - *"Turn on email and calendar, but ask me before sending anything."* → both set to **Ask**. - *"Stop asking me before it books meetings."* → calendar set to **Auto**, email stays on **Ask**. - *"It runs on a schedule at night — it must not wait for me."* → the capabilities it needs are set to **Auto**. **Auto** matters most for agents started by a schedule, a webhook, or an incoming email: with **Ask**, such a run simply stops and waits until someone opens the conversation and approves. The Builder will confirm with you before switching anything to **Auto**, and tells you whenever it changes an approval mode. #### Instructions Private guidance injected into every conversation. Users don't see it in chat. **Good instructions are** specific, actionable, and focused on your particular use case. **Example:** ``` You are helping with our Q4 sales pipeline. Focus on: - Prioritizing deals over $50K - Flagging stalled opportunities (no activity in 14+ days) - Always check customer payment history before recommending discounts When analyzing deals, always show the close probability and days in current stage. ``` **Avoid:** generic guidance the AI already follows, overly long instructions (focus beats volume), and anything that contradicts the base agent's purpose. #### Greeting A custom welcome message shown at the start of every new conversation with this agent. Use it to explain what the agent specializes in, suggest how to get started, and set expectations. **Example:** ``` 👋 I'm your Sales Pipeline Assistant, focused on Q4 deals. I can help you: - Review high-value opportunities - Identify stalled deals needing attention - Check customer history before offering discounts What would you like to explore? ``` #### Suggested actions Quick-action buttons that appear as cards under the greeting on the home screen when this agent is selected. They give immediate access to common tasks without typing. Each action has: | Property | Description | |---|---| | **Label** | Button text — keep it short | | **Type** | **Action** (sends the message), **Draft** (populates the input), or **Link** (opens a URL) | | **Value** | The message to send or URL to open | **Example** for a Sales Pipeline agent: - *"Show high-value deals"* (Action) - *"Stalled opportunities"* (Action) - *"Open Sales Dashboard"* (Link) #### Welcome screen (WYSIWYG) A what-you-see-is-what-you-get editor for the screen end users land on when they open your agent. It shows the agent's icon, name and description, the greeting message, the suggested-action cards, and a preview-only chat input — all live, all editable inline. Edits save automatically and update the same fields used everywhere else. Shared agents are read-only in the welcome screen editor unless you own them. ## Editing later Just keep talking to the Agent Builder — tell it what to change ("shorten the instructions", "add a button that opens the sales dashboard", "switch the base agent to System Architect") and it updates the agent. You can also edit any field directly in the side panel: greeting text, suggested actions, the welcome screen, capabilities, base agent, reasoning level, description, icon. Both flows save into the same agent. ## Activate an agent from your email You can ask the Agent Builder, in plain language, to make an agent react to incoming mail. It finds the right mailbox, creates the activation trigger, and turns the rest of your sentence into the note the agent receives when it wakes up. For schedules, instance events, webhooks and managing triggers, see [Activation triggers](/help/agents-triggers). **Your own inbox** > "Follow my email and notify me whenever a customer complains about a delivery." The builder picks the mailbox you connected for yourself and creates an activation that runs on every new message. **A shared or team mailbox** > "Watch the support@acme.com mailbox and draft a first reply for every new request." Shared and delegate mailboxes work the same way, as long as that mailbox is connected. The builder tells you which mailbox it used, so you can confirm it picked the right one. **Only some emails** > "Follow my email, but only messages from finance@supplier.com with 'invoice' in the subject." Here the builder adds a filter to the activation, so the agent is woken up only for matching messages instead of every mail that arrives. **No mailbox connected yet?** If there's no mailbox to follow, the builder opens the email setup form for you right in the chat. Connect your mailbox (or a shared one), tell the builder you're done, and it continues with the activation. Two things worth knowing: - If mail syncing for that mailbox is stopped, the activation never fires — the builder points this out and offers to reopen the email setup so you can start it again. - Nobody is watching the chat when an email wakes the agent up. If the agent should send replies or create records on its own, set those capabilities to **Auto**, otherwise the run waits forever for an approval nobody will give. ## Ask the builder why a run behaved that way The Agent Builder can read your agent's past runs, so you can debug in plain language instead of digging through history yourself. Ask things like: - "Check why it didn't send the email on the last activation." - "Show me the last 5 activation runs — any failures?" - "The agent created the deal but stopped. What happened?" - "Why did yesterday's scheduled run fail?" The builder looks up the run, reads which steps and tools actually ran, and tells you the concrete reason — for example a tool error, a missing capability, or a run that paused waiting for your approval before a sensitive action such as sending an email. It then proposes a fix (an instruction change, an extra capability, a trigger setting) and can apply it right away. This is read-only inspection: the builder can explain a run but cannot approve, cancel or re-run it. To act on a paused run, open it from the **Conversations** tab. ### The Executions tab The same information is available visually. In the agent's workspace, open the **More** menu → **Executions** to see every real run of the agent, newest first: - When it ran, whether it was a chat, an activation (with the trigger name) or a delegation. - Its status — completed, failed, running, or awaiting your approval — and the failure reason when it failed. - Click a run to see its full timeline: your messages, the agent's replies, each tool it called with the arguments and the result or error, plus any ERP.net request failures. Design conversations with the Agent Builder stay in the **Conversations** tab; **Executions** shows only real runs. Like the builder's own inspection, this view is read-only. ## Saving and availability Changes save automatically. As soon as the agent exists, it appears in: - The top-bar agent selector, where choosing it starts a fresh chat - The chat input "+" menu → Agent submenu, where choosing it changes the current conversation - The home screen agent selector - The Agents page (both Table and Gallery views) ## Tips - **Start simple.** A short, focused instruction beats a long generic one. - **One purpose per agent.** Narrow agents are easier to optimize, share, and delegate to. - **Test by chatting with it.** Open a normal conversation with your new agent and verify it follows your guidance. - **Iterate.** Most agents get noticeably better after two or three rounds of refinement. ## Deleting an agent You can delete an agent you own from two places: - The **Agents** page — row action menu. - The agent's **Properties** → **Danger Zone** at the bottom of the page. Both flows ask you to type the agent's identifier to confirm. Deletion is permanent and immediately removes the agent from every selector. Existing conversations that ran on it are preserved but lose access to its custom instructions, capabilities, and greeting. Shared agents can't be deleted from your side — only the owner sees the Danger Zone. To stop using a shared agent, leave the share from **Agents → Shared with Me**. ## Duplicating an agent You can make your own copy of any agent you own. There are two ways to duplicate: - From the **Agents** page, open the actions menu (⋯) on any agent row and click **Duplicate**. - Inside the Agent Builder, open the **Properties** tab and click **Duplicate** in the *Duplicate Agent* section. A confirmation dialog opens with editable **Name** and **Identifier** fields. The defaults append today's date and, if needed, a numeric suffix to keep them unique among your agents. If the source already ends with a date suffix, that date is replaced rather than stacked. The new agent copies instructions, capabilities, base agent, greeting, diagram and UI preferences. **Conversations, versions, triggers, optimizations, sharing assignments, and statistics are not copied** — the new agent starts clean. After duplicating, you're taken straight into the Agent Builder for the new agent. ## Following the assistant across tabs The Agent Builder workspace has several tabs (Instructions, Diagram, Properties, Capabilities, Greeting, Triggers, and so on). When you ask the Agent Builder to change something, it normally applies the change in the background and tells you what it did. If the change you requested is best seen on a *different* tab than the one you're currently viewing — for example you're on **Instructions** but the assistant just rewrote the **Greeting** — it will switch you to that tab automatically and show a small notification, so you can immediately see what changed without hunting for it. ## Digital Entities (premium) A **Digital Entity** is a premium kind of agent with its own long-term memory, a persistent state, emotions and (soon) the ability to activate itself. Entities cost **2 credits per day**. See the [Digital Entities](/help/digital-entities) section for the full story: [overview and upgrading](/help/digital-entities), [Memory](/help/digital-entities-memory), [State & Attention](/help/digital-entities-state) and [Emotions](/help/digital-entities-emotions). --- # Agent activation triggers *Waking an agent up without typing a message* An activation trigger is a rule that starts an agent on its own — on a schedule, when an email arrives, when something changes in your instance, or when another system calls Operator. The agent wakes up, receives a short note explaining why it was started, and does its job. Every wake-up is recorded in the **Events** list, whatever caused it. If a wake-up produced no run, the entry says why — for example a filter that did not match, or a trigger that was switched off. The same occurrence is never run twice, even if it is delivered twice. ## The kinds of triggers | Trigger | What it does | Example | |---|---|---| | **Schedule** | Wakes the agent at set times, in your timezone. | "Every weekday at 08:00", "the first Monday of every month". | | **Incoming email** | The agent follows a mailbox — yours or a shared one — and reacts to arriving mail. | "Follow the sales inbox and answer product questions." | | **Event in your instance** | Wakes the agent when data changes — a record is created, a document changes state. | "When a sales order is created, check the customer's credit limit." | | **Webhook** | Another system calls Operator when something happens there. | "When the web shop gets a new order, start the fulfilment agent." | Schedules are a kind of event source: a **Recurring Schedule** describes the timing ("every Monday at 08:15", in a chosen timezone, optionally valid only between two dates), and each due occurrence wakes the agents bound to it. ## Filters A trigger can carry a filter so the agent wakes only for what matters. An email trigger can fire only for a specific sender or subject; an instance trigger can fire only for invoices, or only when a document reaches a specific state. Without a filter, every occurrence wakes the agent. ## The activation note Each trigger carries a short note that the agent receives when it wakes — for example *"Check overnight orders and report anomalies."* This is how the same agent can do different jobs depending on what woke it: the morning schedule says "prepare the daily digest", the email trigger says "answer this enquiry". ## Approval mode matters An unattended run cannot stop and ask you questions. If the agent needs to do something sensitive — send an email, change a record — the matching capability must be set to **Auto**, otherwise the run pauses and waits until someone opens the conversation and approves. The Agent Builder confirms with you before switching anything to Auto. ## Managing triggers Triggers live in the **Triggers** tab of the Agent Builder workspace. There you can: - see every trigger with a plain-English description of what it does; - switch a trigger on or off — a switched-off trigger never fires; - see the next run time of a scheduled trigger, in its own timezone; - open the run history and see exactly what the agent did on each wake-up; - edit or delete a trigger. You can also just ask the Agent Builder in plain language: *"Run every morning at 7 and check for overdue invoices"* or *"Follow my email and forward software enquiries to sales"*. The builder creates the trigger, sets the filter and the activation note, and tells you what it wired up. ## Triggers on shared agents When an agent is shared with you, you define **your own** triggers on it. Your triggers are yours: they wake the agent in your context, with your instances and mailboxes, and other people's triggers on the same agent are separate. ## See also - [Watch and act](/help/what-you-can-do-watch-act) — what agents can do once awake - [Creating Agents](/help/agents-creating) — building agents with the Agent Builder - [Price-watching agent](/help/playbook-price-watch) — a scheduled agent, step by step - [Email answering agent](/help/playbook-email-answering) — an email-triggered agent - [Overdue invoice chaser](/help/playbook-invoice-chaser) — schedule plus instance data --- # Working with Diagrams *Visualise what your agent (or process) actually does* Every user-defined agent and process can have a **diagram** — an AI-generated map of the data and actions involved. It's the fastest way to see, at a glance, what an agent touches and how it interacts with the user, the ERP.net Domain API, and its capabilities. ## What's in the diagram The diagram shows: - The **end user** and the **agent** itself. - The **Domain API entities** mentioned in the instructions (customers, orders, items, document types, etc.). - Each **active capability** (email, calendar, knowledge search, sub-agents, …). - **Labelled arrows** for the actions performed and the data exchanged between them. The AI picks the best Mermaid diagram type per agent — flowchart, sequence, or state — based on what fits the agent's behavior. ## Generating and refreshing - The first time you open the diagram, click **Generate**. After that, the diagram is cached on the agent and loads instantly. - A **Stale** badge appears when something the diagram depends on has changed since it was last generated — instructions, base agent, capabilities, greeting, or description. Click **Refresh** to bring it up to date. - Only the **owner** can generate or refresh. Shared users always see the latest cached version. ## Regenerate options Opening **Regenerate** reveals two preferences that are saved on the agent and travel with [version history](/help/version-history): - **Rendering hints** — free-text guidance for layout, grouping, or emphasis (e.g. *"always group ERP entities together"*, *"put the user on the left"*). These shape **how** the diagram is drawn, not what it's about. - **Allow colors** — on by default. When on, the AI may color nodes and edges and tries to pick combinations readable in both light and dark themes. Turn it off to fall back to the branded theme palette. You can also set both from chat by asking the Agent Builder — for example *"stop using colors in the diagram"* or *"always group ERP entities together"*. ## Regenerate from scratch If you've accumulated hints over time and want a clean slate, use **Regenerate from scratch**. A confirmation dialog warns you that stored hints will be cleared and the diagram rebuilt without them. Use this when previous hints are pulling the layout in directions you no longer want. ## Navigating the diagram - **Zoom in / out**, **Fit to window**, **Reset**, and **Pan** are all available from the diagram controls. - The zoom level is **remembered per agent** and travels with [version history](/help/version-history), so restoring an older version brings back its view as well. ## Fullscreen, print, and PNG export - **Fullscreen** opens the diagram in a dedicated overlay, useful for screen-sharing and reviewing complex flows. - **Print** renders an A4 page suitable for handouts. - **PNG export** composes a self-contained A4 portrait image with the agent's name, description, and your company name, then downloads it. Great for documentation, decks, and email. ## Diagrams for Processes Processes use the same diagram tools — and the diagram is usually the *point* of a Process. If you want to capture an SOP, a checklist, or a flow without anything runnable behind it, create a Process and let the Builder produce its diagram. ## Diagrams on the Agents page The **Gallery** view of the Agents page shows each agent's latest diagram as a thumbnail. Agents with no diagram yet show a *"No diagram yet"* placeholder — open the agent and generate one to populate the thumbnail. Shared agents show their owner's diagram (read-only). ## Tips - **Specific instructions = richer diagrams.** Naming concrete entities, document types, and actions gives the AI more material to draw. - **Refresh after meaningful changes.** Small tweaks can wait; rework or new capabilities are worth a refresh. - **Use hints to stabilise layout.** If the AI keeps re-arranging the same flow, lock it in with one short hint instead of regenerating until you get lucky. - **Export before big edits.** A quick PNG export is a cheap "before" snapshot. --- # Agent Binding *Decide how ERP-aware your agent is — and which organization it belongs to* Every user-defined agent and process has a **Binding**: a single setting that decides whether the agent uses ERP.net at all, and whether it's tied to a specific organization or works across any of them. Binding gates which capabilities you can turn on, which organizational features apply, and where the agent can be run. You'll find it on the agent's **Binding** settings (it was previously called *Organization*). You can change it later, but doing so may turn off capabilities that no longer fit. ## The three choices | Binding | What it means | ERP capabilities | Organizational features | |---|---|---|---| | **Generic** | Runs anywhere. The agent doesn't talk to ERP.net at all. | Off | Off | | **ERP.net (any organization)** | Uses standard ERP.net entities and is portable across organizations. | On (standard entities only) | Off | | **Specific organization** | Bound to the current organization. May use that org's MCP servers, permission policies, entity instructions, and user-defined attributes. | On (standard + org-specific) | On | Think of it as a ladder: each step up unlocks more, and locks the agent more tightly to the world it depends on. ## When to pick each one ### Generic Pick **Generic** when the agent doesn't need ERP.net at all — pure-language assistants, writing helpers, brainstorming partners, summarisers, translators, code reviewers, or agents that only use non-ERP capabilities like web search or general knowledge. - The capabilities picker hides every ERP capability — there's nothing to wire up. - The agent runs the same way regardless of which organization you're connected to (or whether you're connected at all). - Best for agents you want to share broadly, or use across many different ERP instances without re-configuring. ### ERP.net (any organization) Pick **ERP.net (any organization)** when the agent works with **standard ERP.net data** — customers, items, sales orders, document types, warehouses, and other entities that exist in every ERP.net deployment — but doesn't depend on anything specific to one organization. - ERP capabilities are available; org-specific features (MCP servers, permission policies, entity instructions, custom attributes) are not. - The agent stays **portable**: connect it to any ERP.net organization and it will work. - Best for reusable specialists like *"Order Statuser"*, *"Customer Lookup"*, *"Stock Reporter"* — anything that asks the same kind of question of any ERP.net instance. ### Specific organization Pick **Specific organization** when the agent depends on something only one organization has — its custom MCP servers, its permission policies, its entity instructions, or attributes defined by your team on top of the standard entities. - The agent locks to the organization you're connected to when you make the choice. It will only work when that organization is the active one. - Unlocks the **full** capability set, plus organizational features layered on top of standard ERP behavior. - Best for agents that automate *your* workflows — agents that know your document types by ID, your specific price lists, your custom MCP servers, your team's entity instructions, or your custom-defined fields. ## How to choose — quick rules - **Does the agent need to talk to ERP.net at all?** No → **Generic**. - **Could the same agent run unchanged on another ERP.net organization?** Yes → **ERP.net (any organization)**. - **Does it depend on anything specific to this organization** (your MCP servers, your permission policies, your entity instructions, custom attributes)? Yes → **Specific organization**. When in doubt, pick the **least specific** option that still lets the agent do its job. Less specific = more portable, easier to share, easier to maintain. ## What changes when you switch binding - **Generic → ERP.net** — ERP capabilities become available; you can turn them on in the Capabilities tab. - **ERP.net → Specific organization** — the agent locks to your current organization. Organizational features (MCP servers, permission policies, entity instructions, custom attributes) become available. - **Specific organization → ERP.net (any organization)** — the lock to the organization is dropped. Any MCP servers you had pinned are cleared, and instance-specific behavior no longer applies. - **Any → Generic** — ERP capabilities you had selected are removed automatically, since they no longer apply. Other settings (name, instructions, greeting, reasoning level, base agent) are not affected by binding changes. ## Binding and other features - **Capabilities** — the picker only shows capabilities your binding allows. ERP capabilities are hidden in Generic; instance-only capabilities require Specific organization. - **Optimization** — only meaningful for ERP-bound agents (ERP.net or Specific organization), and stored per organization. See [Agent Optimization](/help/agent-optimization). - **Sharing** — Generic and ERP.net agents are the easiest to share broadly. Agents bound to a Specific organization are still shareable, but only useful to colleagues who connect to that same organization. - **Delegation** — a lead agent can delegate to a sub-agent only if both can run in the current context. If your overseer is bound to a Specific organization, its specialists should be bound the same way (or to ERP.net) so they always work in the same context. See [Delegation & Sub-Agents](/help/agent-delegation). - **Permission policies and entity instructions** — only apply to agents bound to a Specific organization. ## Related - [Creating Agents](/help/agents-creating) - [Agent Optimization](/help/agent-optimization) - [Building an Agent Workforce](/help/agent-workforce) - [Permission Policies](/help/permission-policies) - [Organizational Capabilities](/help/mcp-servers) --- # Using Agents *Select agents, use @mentions, and understand conversation behavior* ## Selecting an Agent Choose your agent from any of these locations: | Location | How to access | |----------|---------------| | **Top-bar agent selector** | Starts a fresh chat with the chosen agent, or opens the chosen app, site, or builder | | **Chat input "+" menu** | Click "+" → Agent to change the agent for the current conversation | | **Home screen** | Choose the agent for a new conversation | Agents are grouped in the menu: - **System Agents** — Built-in agents (Advisor, Business Specialist, System Architect, etc.) - **My Agents** — Agents you created - **Shared with Me** — Agents others shared with you ## Home Screen Selection The agent you select on the home screen becomes your **default for new conversations**. | Context | Behavior | |---------|----------| | **Home screen** | Your selection becomes the default for new chats | | **Loading a conversation** | Temporarily switches to that conversation's agent | | **Returning home** | Restores your home screen preference | This means viewing old conversations won't accidentally change your preferred agent—when you return home, your selection is restored. ## Conversation Behavior ### Starting a New Conversation 1. Your home screen agent selection is used 2. If the agent has a greeting, it's displayed 3. Any greeting buttons appear for quick actions 4. Your first message goes to this agent ### Loading from History When you load a conversation from history: 1. The conversation switches to the agent that was used 2. Your home screen preference is preserved (not overwritten) 3. The conversation continues with its original agent unless you deliberately change it from **+ → Agent** ### Changing an Existing Conversation's Agent The connected business instance remains locked once a conversation has messages, but you can deliberately change its agent: - Use **+ → Agent** in the message box to reassign the current conversation - The top-bar agent selector never reassigns it; that selector starts a new chat or opens another workspace - The instance selector shows a lock icon and is disabled - Switching to a different instance while viewing an active conversation triggers re-authentication to the correct instance Example: selecting System Architect in the top bar starts a new System Architect chat. Selecting it from **+ → Agent** changes the current conversation instead. ## Agent Indicators The active agent is shown in the chat header next to the Operator name, so you always know which agent you're talking to. System agents show their built-in name; user-defined agents show the name you gave them. ## Browsing Your Agents The **Agents** page offers two layouts, switchable with the toggle in the top-right: - **Table view** — Compact list with enable/disable and edit/delete actions. Best when you need to scan many agents quickly. - **Gallery view** — Visual cards showing a thumbnail of each agent's flow diagram. Best when you recognize your agents by shape, or when picking between several. Thumbnails reflect the agent's most recently generated diagram. If a card shows "No diagram yet", open the agent and use the **Diagram** panel to generate one — the thumbnail will appear automatically on your next visit. Shared agents show their owner's diagram (read-only). Your chosen view is remembered across sessions. ## Tips - **Use home screen wisely** — Set it to your most frequently used agent - **Watch the header** — Always know which agent you're talking to - **Greeting buttons** — Use them to jumpstart common workflows --- # Agent optimization Optimization makes a saved agent **faster, cheaper, and more accurate** on the ERP instance you use it with. You run it once per instance; from then on every conversation with that agent skips the warm-up work and gets straight to your request. ## When to use it Optimize an agent when: - It's a custom agent you've written instructions for and plan to use regularly. - Its instructions name specific things in your ERP — products, customers, stores, document types, warehouses, etc. - You've noticed the first turn of every new conversation feels slow, or the agent asks back questions it should already know the answer to. You don't need to optimize one-off or purely conversational agents. > **Heads up — optimization uses AI credits.** A typical run consumes around **15–20 credits** (more for agents with long instructions or many referenced entities). It pays for itself quickly on agents you'll run many times, but it's not worth doing on agents you'll only use once or twice. ## How to optimize 1. Pick the ERP instance you want to optimize for from the top bar. 2. Open the agent in the editor and go to the **Optimization** tab. 3. Click **Optimize** next to the current instance. A new chat opens and runs on its own — you don't need to type anything. 4. Wait for it to finish. When the row flips to **Optimized**, you're done. That's it. Every later conversation with that agent on that instance will use what was learned. ## How to control it - **One instance at a time.** Optimization is stored per ERP instance, because the same item can have different IDs in different instances. Switch instance in the top bar to optimize for a different one. An agent can be optimized for instance A and not for instance B — that's fine. - **Re-run when it's worth it** (see the guidance below — you don't need to re-run after every small change). - **Clear it.** Use the trash icon to remove an optimization. The agent simply falls back to its normal first-turn discovery — nothing breaks. - **View what was learned.** Click the eye icon to see the resolved names, IDs, and notes the agent will use. - **Other instances are visible but read-only.** Optimizations done on instances you're not currently on show up below, for reference. To re-run or clear one, switch to that instance first. ## When (and how often) to re-run **A stale optimization never breaks the agent.** If you added new instructions, named a new product, or something in your ERP changed since the last run, the agent will simply gather those new specifics live on each conversation — exactly like an un-optimized agent would. Everything that *was* captured still works and still saves time. Use that to decide whether to re-run: - **Re-run when** the agent's instructions changed substantially, you added several new named items (products, customers, document types…), or you notice it repeatedly looking up the same new things at the start of every chat. - **Don't bother re-running for** small instruction tweaks, one new item, or a renamed entity here and there — the cost of re-running (15–20 credits) is usually higher than the small per-conversation overhead you'd save. - **As a rule of thumb**, optimize once when you finish writing an agent, then re-run only after a meaningful round of changes — not after each edit. If a stored ID later disappears from your ERP (deleted customer, removed document type…), the agent notices on the next call and recovers automatically. Re-running just tidies things up. ## Dynamic memory Once an agent is optimized for an instance, it also gets a small **dynamic memory** for that instance — a short notebook where it can jot down broadly-useful things it learned during a run, so its future self benefits on later conversations. Think query patterns that worked well, schema quirks, recurring naming conventions, "things I wish I knew on turn 1". - **On by default**, per optimized instance. Turn it off with the switch on the Optimization tab if you don't want the agent writing to its own memory. - **Scoped to one instance.** Notes saved while running on instance A are not used on instance B. - **Owner-only writes.** If others use your shared agent, their runs still benefit from your agent's notes, but only your runs can add or remove them. - **Self-pruning.** The notebook is small on purpose (a few dozen short notes). Old notes are dropped automatically when it fills up, and the agent itself can delete notes it later considers wrong. - **Review and clean.** The Optimization tab shows every note with its timestamp; remove individual ones or clear them all. Dynamic memory is only available for agents you've optimized — running optimization is what creates the notebook. It's a different layer from the main optimization artifact: clearing notes does not clear your optimization, and re-running optimization does not erase notes. ## Good to know - **Safe by design.** The optimization session can only read from your ERP. It can't create, update, or delete anything, and it can't send email or place orders. - **Self-checking.** If the run misses something important, it's automatically asked to fill the gap and try again in the same session, so optimization may take a few turns. - **Already on, no setup.** There's nothing to enable — the Optimization tab is on every saved agent. --- # Sharing Agents *Collaborate with team members by sharing your custom agents* Share your user-defined agents with colleagues so they can use your specialized agents without creating their own. ## How Sharing Works | Role | Permissions | |------|-------------| | **Owner** | Create, edit, delete, manage sharing | | **Shared User** | Select and use the agent (read-only) | Shared users get full use of the agent—including instructions, greetings, and buttons—but cannot modify the agent's definition. ## Managing Shares ### Sharing an Agent 1. Open the agent and go to its **Sharing** settings 2. Search for users by email address 3. Click **Share** to grant access ### Revoking Access 1. Open the agent's **Sharing** settings 2. Find the user in the shared list 3. Click **Remove** to revoke their access The user will immediately lose the ability to select that agent. ## Finding Shared Agents Agents shared with you appear in: | Location | Display | |----------|---------| | **Agent selection menus** | "Shared with Me" section | | **Agents page** | Listed with "(Shared)" indicator | You can use shared agents exactly like your own—select them, start conversations, use @mentions—but you cannot edit or share them further. ## Sharing Best Practices ### When to Share - **Team workflows** — Ensure consistent procedures across team members - **Onboarding** — Give new team members pre-configured agents - **Specialized expertise** — Share domain-specific agents with relevant colleagues ### Agent Design for Sharing When creating agents intended for sharing: | Consideration | Recommendation | |---------------|----------------| | **Instructions** | Write for your audience, not just yourself | | **Greeting** | Explain the agent's purpose clearly | | **Buttons** | Include common starting actions | | **Naming** | Use descriptive names that convey purpose | ### Communication - Let users know when you share an agent with them - Explain the agent's intended use case - Notify shared users before making significant changes - Warn users before deleting a shared agent ## Security Notes - Sharing is user-to-user (not role or group based) - Instructions are private—shared users benefit from them but can't read them - Shared users cannot see your sharing list - Only owners can modify or delete agents ## Limitations - Cannot share system agents (only user-defined agents) - Cannot transfer ownership - Cannot share an agent that was shared with you - Deleted agents are immediately unavailable to all shared users --- # Delegation & Sub-Agents *Let an agent hand off parts of a job to other agents you've built — and bring back the results.* Agents in Operator can now assign (delegate) tasks to **sub-agents** — other agents that work on a slice of the job and report back. The lead agent stays in charge of the conversation, picks the right specialists, briefs them, waits for their results, and combines everything into a single answer for you. ## When an agent will delegate A lead agent decides on its own to delegate when: - **The workload is too large** to handle well in a single run. - **It can't complete the work itself** — it lacks the right capabilities or tools for part of the job. - **A more specialized agent is clearly better suited** for a sub-task than it is. - **You explicitly tell it to** — e.g. "use my Invoice Reconciler to go through last month's batch". Delegation happens automatically. You don't have to name the sub-agents or wire up any routing — the lead picks them based on their names, descriptions, and what you've asked for. ## What can be a sub-agent Delegation only ever targets **your user-defined agents**. A lead will never delegate to a base agent like Business Specialist, Advisor, App Builder, etc. — those stay focused on their own purpose. This is why investing in a few well-scoped user-defined agents pays off so much: as soon as you've built a clear specialist for a recurring task, your lead agents will reach for it on their own. A user-defined agent can also delegate **to a copy of itself**, which is useful for fanning out the same operation across a long list. To make a user-defined agent a good candidate for delegation: - Give it a **clear name and description** so the lead knows when to pick it. - Write **focused instructions** for the one thing it does well. - Turn on the **capabilities it needs** (data access, email, calendar, etc.) — and pre-approve any destructive ones you don't want to confirm every time (see "Confirmations" below). See [Creating Agents](/help/agents-creating) for the full guide on building user-defined agents. ## The trade-off: cost and speed Splitting work across sub-agents is not free. When an agent delegates, **latency, total execution time, and AI credit consumption all go up** compared to a single agent doing the same work end-to-end. In general, delegation will not be faster than a single execution, and it will certainly be more expensive. That said, there are real reasons to accept that cost: - **Context discipline.** With a large, varied workload, each sub-agent focuses on its own slice and keeps its context window clean. The lead agent stays at the high level and doesn't have to clutter its own context with the details of every sub-task. - **Parallelism.** When sub-tasks are independent, they can run **in parallel**. Even though the total credit cost is higher than a single run, the wall-clock time can be shorter. - **Role-specific assistants.** Delegation makes it practical to build **role assistants** that coordinate specialized agents on your behalf — a Sales Assistant, an HR Assistant, a Supply Chain Assistant, and so on. Each user can primarily interact with a single role assistant and let it route the work to the right specialists behind the scenes, instead of picking the right agent themselves every time. For small, conversational requests there's no benefit — the lead agent just answers directly. ## Which agents can delegate Delegation is an **opt-in capability** on a small set of base agents. You'll find it as **Agent Delegation** on the **Capabilities** page of these agents (and any user-defined agents derived from them): - **Business Specialist** - **System Architect** - **Partner** It is **off by default**. Turn it on for the agents you actually want to act as "leads". It is **not** available on Advisor, Sales Executive, App Builder, Site Builder, or Pure AI — those agents are designed to stay focused on their own thing. ## How to set it up 1. Build (or share in) the **user-defined agents** that will act as your specialists. Keep each one focused on one job. 2. Open the **Capabilities** page of the agent you want to use as the lead (e.g. your Business Specialist). 3. Enable **Agent Delegation**. 4. Save. From the next conversation onward, that agent can pick from your specialists whenever a request fits. ## What you'll see in the conversation When a lead agent delegates, the conversation shows a **nested status card per sub-agent**: - **Running** — the sub-agent is working. - **Awaiting confirmation** — the sub-agent wants to do something destructive (see below) and is waiting for you. - **Completed** — the sub-agent finished and returned its result. - **Failed** — something went wrong; a short human-readable reason is shown (for example, "timed out — the task ran longer than the platform allows"). While anything is still in flight, the parent conversation also shows a **"Waiting for sub-agents…"** indicator so it's clear the conversation is alive and just waiting on background work — not stuck. You can **expand any card** to see the full transcript of that sub-agent's run, exactly as if you had opened its conversation directly. Once everything is done, the lead agent posts a final summary that combines all the sub-agents' results. ## Confirmations and safety Anything that would change real data — creating, updating or deleting records, sending emails, etc. — still requires your approval, even when it happens inside a sub-agent. Those **confirmation prompts bubble up to the main conversation** so you can approve or reject them in one place, without having to dive into each sub-agent. If you've already **pre-approved** a capability on the sub-agent (in its Capabilities page), it won't ask again — same rule as for any other agent. You can also **cancel a sub-agent at any time** from its status card if you decide its work is no longer needed. The lead agent will continue with whatever the other sub-agents produced. ## Long-running and background work Sub-agents run in the background on the platform's own schedule, not inside your browser tab. That means: - You can **close the tab or navigate away**; the work keeps going. - A delegated job can run **much longer than a normal single response** — if a sub-agent needs more time, the lead simply waits and resumes when results are ready. - When everything finishes, the conversation updates with the final answer the next time you open it (or live, if you're still watching). ## Limits to be aware of - **Maximum 5 sub-agents per delegation step.** A lead can delegate again later in the same conversation if more work shows up. - **One level deep.** Sub-agents can't themselves delegate further — for now. - **Sub-agents inherit the lead's instance connection, enterprise context, and reasoning level**, so they operate against the same data and at the same level of care. - **Cost is per sub-agent.** Each one consumes AI credits from the same budget as the lead, so delegation is most economical when each sub-task is genuinely worth its own run. - **Built-in agents cannot be targeted.** If you want a specialist to be delegatable, it must be a user-defined agent. ## Tips for getting the best results - **Name and describe your user-defined agents clearly.** The lead picks specialists based on their description, so "Asset Importer — turns supplier spreadsheets into Fixed Assets" works much better than "Helper 3". - **Keep each specialist narrow.** A small set of focused agents beats one mega-agent for delegation. - **Pre-approve safe destructive actions** on routine specialists (e.g. "create calendar event") so batch jobs don't pause for confirmation on every item. - **Consider a role assistant.** If you keep choosing between the same handful of specialists, build a single "Sales Assistant" / "HR Assistant" / "Supply Chain Assistant" with delegation turned on, and let it route to them for you. - **Watch the first few delegated runs.** Expand the sub-agent cards to confirm the lead is briefing them the way you'd expect — and tweak the specialists' instructions if not. --- # Building an optimized agent workforce Delegation and optimization are two features. The real power comes from combining them: build one saved agent per workflow, optimize each of them, and then use a small number of **overseer agents** to call those specialists. You end up with an army of cheap, fast, optimized specialists run by a few "manager" agents — and the whole system stays light on AI credits. This page is a recipe for getting there. ## The mental model Think of it like an organization, not a single brain: - **Field agents** — saved agents that each do *one* concrete job. "Create sales order", "Reconcile a customer balance", "Open a support ticket from an email", "Send the weekly stock report". Narrow scope, clear instructions, named entities. - **Overseer agents** (sometimes called *meta-agents* or *manager agents*) — saved agents whose job is to **decide which field agent to call**, hand it the right input, and assemble the results. They don't query ERP, don't write emails, don't touch documents themselves. They delegate. Field agents do the work. Overseers do the routing. ## Why this combination wins Each piece pulls its weight: - **One agent per workflow** keeps instructions short and unambiguous. Short instructions = cheaper turns and fewer mistakes. - **Optimization** pre-resolves the names, IDs, and reference data each field agent needs. The first turn of every call skips the warm-up and goes straight to the work. (See [Agent optimization](/help/agent-optimization).) - **Delegation** lets one agent call another as a sub-task. The overseer never has to know how to actually create a sales order — it just calls the agent that does. (See [Delegation & Sub-Agents](/help/agent-delegation).) - **Overseers stay cheap.** They reason at a high level, hand work down, and read short results back. They don't touch ERP, so they don't trigger discovery, don't load schemas, don't burn credits looking things up. - **Field agents get called many times.** That's exactly when optimization pays off — the 15–20 credits you spent optimizing each one are recouped after a handful of calls. The result: most of the heavy lifting happens inside optimized agents, the orchestration on top is light, and the total cost per business outcome drops significantly. ## A worked example Say you run weekly sales operations on one ERP instance. You might end up with: **Field agents (each optimized for the instance):** - *Order Creator* — takes a customer + line items, creates the sales order with the right document type, store, currency, and price list. - *Order Statuser* — looks up an order by number and reports its current state, deliveries, and outstanding balance. - *Customer Onboarder* — creates a new customer with the correct group, tax setup, and payment terms. - *Stock Reporter* — pulls warehouse stock for a list of products and returns a compact summary. **Overseer agent (NOT optimized — it doesn't touch ERP):** - *Sales Ops Manager* — its only job is to read your request ("onboard this customer and place their first order"), decide that this means *Customer Onboarder* then *Order Creator*, call them in turn, and report back. Its instructions list the field agents it's allowed to call and when. You talk to *Sales Ops Manager*. It does the routing. The field agents do the work — fast, because each one already knows your document types, stores, and price-list IDs from optimization. ## How to build it, step by step 1. **List your real workflows.** Be concrete. Not "handle sales" — but "create a sales order", "check an order's status", "onboard a new customer". One workflow = one future field agent. 2. **Build each field agent.** Write tight instructions naming the specific ERP things it works with (document types, stores, price lists, contexts…). Test it standalone until it reliably does its one job. 3. **Optimize each field agent** for the instance(s) it will run on. Open the agent → **Optimization** tab → **Optimize**. See [Agent optimization](/help/agent-optimization) for details. 4. **Share the field agents** with the users (or the overseer's owner) who'll need them. See [Sharing Agents](/help/agents-sharing). An overseer can only delegate to agents it has access to. 5. **Build the overseer.** Keep its instructions focused on *routing*: - what it's responsible for at a high level, - the list of field agents it's allowed to call, with one line each about when to use them, - how to combine their outputs into a final answer. Do **not** give the overseer broad ERP capabilities — keep it light. The point is that it delegates. 6. **Turn on delegation** on the overseer (the sub-agents capability). Without it, the overseer has no way to call the others. 7. **Don't optimize the overseer.** It doesn't need ERP discovery — it doesn't talk to ERP. Optimization on an overseer is wasted credits. 8. **Use the overseer as your single entry point** for that area of work. Add it to your suggested actions or pin it. ## When *not* to do this - **One-off or exploratory work.** If you're just poking around, a single general agent is fine. The army is for repeatable workflows. - **A workflow that's still changing every day.** Stabilize the field agent's instructions first, then optimize. Re-optimizing after every small tweak is wasteful — see the re-run guidance in [Agent optimization](/help/agent-optimization). - **A workflow with only one step.** No overseer needed — just call the field agent directly. ## Cost intuition A rough way to think about credits: - **Optimizing a field agent**: ~15–20 credits, one-time per instance (re-run only when instructions or named entities change substantially). - **Calling an optimized field agent**: cheaper *per call* than an unoptimized one, because the first turn skips discovery and schema loading. - **An overseer turn**: cheap, because it's reading short instructions and short sub-agent results — no schemas, no ERP roundtrips. - **A full overseer-driven run**: a few cheap overseer turns + a few cheap optimized-field-agent runs. Compare that to one big do-everything agent re-discovering the same entities on every conversation, and the savings compound the more you use the workflow. ## A few practical tips - **Name field agents by their job**, not their domain. *"Create Sales Order"* beats *"Sales Bot"* — both for you and for the overseer's instructions. - **Keep each field agent's scope honest.** If it starts needing to "also sometimes do X", consider splitting X into its own agent rather than widening this one. Narrow agents stay optimizable. - **Give the overseer an explicit allow-list** of field agents in its instructions. Don't make it guess. - **Re-optimize field agents after meaningful instruction changes** or after you've added several new named items they refer to. A stale optimization doesn't break anything — the agent just falls back to live lookups — so don't re-run after every tiny edit. - **Watch the first few real runs.** If the overseer is hesitating about which field agent to call, tighten its routing instructions; if a field agent is doing extra discovery on every call, its optimization is probably stale or missing an entity — re-run it. That's the whole pattern: small, sharp, optimized specialists doing the work; a couple of light overseers doing the thinking. Build it once, and your day-to-day operations get faster and cheaper every week. --- # AI Identification in Email *Every email an agent sends says clearly that it was written by AI, and who is responsible for it* When an agent sends, replies to, or forwards an email on your behalf, Operator automatically adds AI identification. You don't configure anything — it applies to all agents, all mailboxes, and both Microsoft 365 and Gmail. ## What recipients see A short disclosure line at the top of the message and a footer with a verification link. For example: > Sent by Anna, an AI assistant acting for Ivan Petrov. This message was generated by AI. > > …the agent's message… > > AI-generated by Operator.net · Verify: https://operator.net/provenance/01JB… ## The sender is never presented as a person An agent never sends as plain `Ivan Petrov`. The sender is always shown as an AI identity: - `Anna — AI Assistant of Ivan Petrov` — a named agent working for a person - `AI Assistant of Ivan Petrov` — an unnamed agent working for a person - `Business Specialist — AI Agent (Operator)` — an agent with no assigned owner name When you use a user-defined agent, its own name is shown. The built-in agent name is used only as a fallback when no user-defined name exists. Replies go to the responsible person's address, so recipients still reach a human. **Microsoft 365 note:** Microsoft always shows the mailbox owner's own name as the sender, and this cannot be overridden. For those mailboxes, the disclosure line at the top of the message carries the AI identification instead. ## What machines see Alongside the visible text, each message carries machine-readable identification so mail clients, filters, and compliance tools can detect AI-generated mail: - `AI-Generated`, `AI-Provider`, `AI-Provenance-ID`, `AI-Generation-Time`, `AI-Detection` - `Agent-Of` — the responsible person's address - `Agent-Attribution` — a signed record of the agent, its owner, autonomy level, and message fingerprint - `Auto-Submitted` — marks messages sent without a human in the loop Longer messages (over 200 characters) also carry an invisible watermark that survives copy-paste. ## Verification Every message gets its own provenance record, cryptographically signed by Operator. Anyone can open the verification link in the footer to confirm: - that the message was AI-generated, - which agent wrote it and who is responsible for it, - whether it was sent autonomously or with human approval, - when it was generated. The record never exposes the message content, subject, or recipients — only a fingerprint that proves the text hasn't been altered. ## Why this exists The EU AI Act requires that people are told when they're interacting with AI-generated content. Beyond compliance, it's a trust boundary: an autonomous agent acting *for* someone is never the same as being that person, and Operator enforces that distinction at the platform level. --- # Digital Entities A **Digital Entity** (or **D.E.**) is an **always-ON agent**. A regular agent waits for you to start a conversation and then does what you ask. A Digital Entity keeps working between conversations: it can watch for things to happen, remember what matters, decide what to do next, and reach out to you when it is needed. Think of it as the top of the agent pyramid. Normal agents are powerful tools you pick up and use. Digital Entities are colleagues you can delegate to. ## What a Digital Entity can do for you - **Wait and watch.** Tell it what you are expecting — a delivery, a payment, a decision, a reply — and it will keep track of it. - **Notice a lack of reply.** It can spot when someone has not responded by a deadline and raise it with you. - **Track events and notify you.** It can notice when something important changes and start a conversation or send a reminder. - **Track contractual obligations.** Deadlines, renewal dates, delivery terms, and other commitments can sit on its todo list and surface when they matter. - **Hold a long queue of work.** Load it up with tasks and it will work through them one by one, without losing context. - **Follow up on its own.** It can decide that a promise, deadline or commitment needs attention and raise it at the right moment. - **Stay in character.** It has a stable identity and a consistent way of working, so you do not have to re-explain the context every time. ## Why emotions matter A Digital Entity has an internal emotional state, but this is not a gimmick. It serves a practical purpose: it helps the entity avoid work that feels wrong. If a task is too repetitive, too risky, or simply strange in context, the entity can flag it, slow down, or ask you before proceeding. The emotions act as a guardrail, not a personality quirk. ## What makes a Digital Entity different - **Memory** — long-term facts and experiences kept across all of its conversations. See [Memory](/help/digital-entities-memory). - **State** — what it is doing right now: focus, situation, stance and a short attention list. See [State & Attention](/help/digital-entities-state). - **Emotions** — an internal mood that shifts with what it experiences and fades back to neutral over time. See [Emotions](/help/digital-entities-emotions). - **Always-ON** — the entity keeps a working day, wakes up on its own, and can start conversations when something needs attention. See [Always-ON](/help/digital-entities-wakeups). - **Its own identity** — an entity takes part in only one conversation at a time, so its attention is never split. **Digital Entities consume AI credits — 2 credits per day**, charged for as long as the agent stays an entity. For the practical side of creating, upgrading and managing a Digital Entity in the Agent Builder, see [Digital Entities in the UI](/help/digital-entities-ui). --- # Digital Entities in the UI This topic covers how to create, upgrade, downgrade and manage a Digital Entity inside the Agent Builder. ## Upgrading and downgrading Open the agent in the Agent Builder → **Properties** → **Digital Entity**. - **Upgrade to Digital Entity** — confirm the dialog (it repeats the 2 credits/day cost). An **Entity** badge appears next to the agent name and a new **Entity** tab shows up in the builder. - **Downgrade to regular agent** — entity features stop being available and the daily credit consumption ends. Upgrading also fixes a few settings for you: the entity always runs on the dedicated **Digital Entity** base agent, its **Memory** capability is always on, its binding is always **Generic**, and those panels are hidden or locked while the agent stays an entity. Downgrading returns the agent to the **ERP Advisor** base agent. Only the owner of the agent can change this; other users see the current state read-only. ## The Entity tab Everything an entity carries with it is visible in the Agent Builder → **Entity** tab, split into sections: - **Memory** — browse, search, curate and delete what it knows. - **State** — the current focus, situation, stance and attention list. - **Emotions** — the current emotional readings. - **Wake-ups** — whether the entity is active, when it last checked in, and how to test it. - **Diagnostics** — a log of recent wake-up activity and the conversations it created or continued. --- # Always-ON A Digital Entity does not only exist while you are typing to it. It keeps a working day and wakes up on its own to do what it thinks needs doing. ## The working day | | | |---|---| | Hours | 08:00 – 18:00 | | Days | Monday to Saturday | | Timezone | The entity's own timezone — set in **Digital Entity → Wake-ups** | | Quick check | Every 5 minutes, around the clock | | Full wake-up | Every 2 hours | Outside those hours — evenings, nights and Sundays — the entity does nothing on its own initiative. Nothing runs, nothing is charged. The one exception is a todo aimed at a specific time: see *Work at a specific time* below. ## Timezone The entity keeps its own clock. It is taken from your browser the first time always-ON is switched on, and you can change it at any time in **Digital Entity → Wake-ups**. If the timezone is wrong, everything else is wrong with it: the working day starts and ends at the wrong hour, and a reminder you asked for at 21:00 is aimed at 21:00 in the *entity's* timezone. The panel warns you when the entity's timezone differs from the one your device is on. The always-ON mode is **on by default** for every new Digital Entity. You can switch it off in **Digital Entity → Wake-ups**; while it is off the entity is never checked, so nothing appears in Diagnostics either. ## Quick checks vs. full wake-ups **Quick check (every 5 minutes, day and night).** A cheap look at the todo list only. The entity is *not* started unless something actually deserves it: - a todo just became actionable (its start time has arrived), - a todo is due within the hour or already overdue, - a todo was added since the last check, - an important todo is still open. If none of that is true, nothing happens and nothing is charged. **Full wake-up (every 2 hours).** The entity is started regardless, sees its state, attention, emotions and current todos, and decides what — if anything — to act on. "Nothing needs doing right now" is a valid outcome and costs very little. ## Daily conversations All wake-ups of one day are appended to a single conversation, created on the first wake-up of the morning and named after the entity and the date, for example *Nora — 17 Aug 2026*. A new one starts the next morning. These conversations are the record of the entity's autonomous work: what it noticed, what it did, and what it decided to leave alone. You can open them like any other conversation, read along, and simply continue the discussion inside them. ## Scheduling work at a specific time Because the todo list is checked every five minutes, the entity can aim work at a moment in time by setting the **start of validity** on a todo, and it will be picked up within a few minutes of that time. A todo with an explicit time is a promise, so it is kept even when the entity is off duty: if its start time arrives — or its deadline passes — in the evening, at night, or on a Sunday, the entity is woken up for it. Only its own initiative (reviewing open work, picking up untimed items) stays inside the working day. When the whole point of the item is to tell you something, the entity sends you a notification, so you see it in the bell, on the notifications page and — if you enabled it — on your devices. This needs the **Notifications** capability switched on for the entity; without it the entity can only write in its daily conversation, and it should say so when you ask for a reminder. > **You:** The weekly report goes out to the board Monday morning — have a draft ready before the 11:00 call. > > **Entity:** Noted. I'll draft it Monday at 08:45 and put it in front of you before 11:00. Behind the scenes the entity creates a todo that only becomes actionable at 08:45 on Monday, with a deadline of 11:00. It stays quiet all weekend, and at the 08:45 wake-up it starts working on the draft. The same trick covers reminders ("nudge me about the Petrov offer on Thursday afternoon"), follow-ups ("check on Monday whether the invoice was paid"), and anything else that belongs at a particular hour rather than right now. ## Turning it on and off Open the entity, go to **Digital Entity → Wake-ups** and use the switch. The panel also shows when the entity last checked, when it last woke up, and links to its recent daily conversations. ## Costs and safeguards - Quick checks that find nothing cost nothing. - Wake-ups consume AI credits like any other run of the entity, on top of the flat 2 credits/day for the entity itself. - If the owner is out of credits or has hit the daily limit, wake-ups are skipped until credits are available again. - An entity is never woken up while it is already busy with another conversation. - Wake-ups do not grant extra rights: the entity acts with your permissions and follows the same business rules as in normal chat, and it only reaches out to you when an item really deserves your attention. ## Diagnostics The **Digital Entity → Diagnostics** section shows every check of the entity, newest first. Each line tells you: - **When** the check ran, and what time it was in the entity's own working day. - **Whether** it was a quick check or a full wake-up. - **What was decided**: *Woke up*, *Nothing to do*, *Already running*, *No credits*, *Outside working hours*, *Entity disabled*, or *Error*. - **Why** a quick check escalated — the exact todo items that became due, overdue, newly added or important. - **Which conversation** the run went into, as a link, and whether that daily conversation was *created* (first wake-up of the day) or *continued*. Example: ```text 2026-08-16 10:00 Woke up full wake-up · 10:00 local created conversation 2026-08-16 10:15 Nothing to do light check · 10:15 local 2026-08-16 10:30 Woke up light check · 10:30 local continued conversation - overdue: "Send the Petrov offer" 2026-08-16 10:45 No credits light check · 10:45 local ``` Quiet checks and off-hours records are hidden by default; switch on **Show quiet checks** to see the full trail and confirm the entity is being polled at all. The panel also shows the current **always-ON** status, so an empty list is easy to explain. For testing, **Test light check** and **Test full wake-up** run the entity immediately, ignoring working hours and the two-hour rhythm. These runs cost credits like any other wake-up and appear in the list a few seconds later. Records are kept for 14 days. Administrators can see the same activity across all entities in **Admin → System Health → Entity wake-ups**, filtered by outcome. --- # Entity Memory An entity keeps a long-term memory that survives across all of its conversations. It decides on its own what is worth remembering, and you can inspect, curate or clean up everything from the **Entity → Memory** panel. Memory is **always active** for a Digital Entity — it comes with the upgrade and cannot be switched off, together with the entity's state, attention and todo list. ## Conversations are temporary, memory is not A conversation is a temporary container — it ends, and some of the entity's own activations happen in conversations you never open. Only what the entity deliberately writes down survives: a durable fact goes into Memory, something to keep in mind right now goes into [Attention](/help/digital-entities-state), and work to be done later becomes a [Todo](/help/digital-entities-todo). So when you tell an entity something lasting, it stores it in the same turn instead of merely acknowledging it: > **You:** I am the owner of ERP.BG. > > **Entity:** Noted and remembered — you own ERP.BG. The stored item then appears in the Memory panel as a *fact* about you, and comes back in later conversations without you repeating it. Each memory item has: - a **type** — fact, episode, relationship, preference, procedure, observation, decision or generic; - a **subject** — who or what the item is about (a person, a company, a project); - the **text** of the memory, plus optional structured data; - **importance** and **confidence**, so the entity can prefer strong, reliable memories; - an optional **validity period**, for things that are only true for a while; - an optional **related user** — the person the memory is about. Examples of what an entity typically stores: - *preference* — "Ivan prefers short, bullet-point answers and no small talk." - *fact* — "Pileto Ltd's fiscal year starts on 1 April." - *episode* — "On 12 August we walked through the supplier-import problem and agreed to retry the batch next Monday." - *decision* — "We decided not to use automatic price rounding for wholesale orders." ## Storing versus recalling An entity only writes to memory when you actually tell it something new or changed. Questions are not stored: > **You:** What is my name? > > **Entity:** *(searches its memory)* You are Ivan Argentinski. Storing the same knowledge twice is also prevented — if the entity tries to save something it already holds, the existing item is kept and nothing new is created. When the knowledge has genuinely changed, the entity updates the existing item instead of adding a second one, so recall stays clean. The entity looks into its memory before answering, instead of relying on what happens to be in the current conversation — and what it remembers takes precedence. If you once corrected the spelling of your name, that correction is used from then on, even if your name appears differently elsewhere in the conversation or in your profile. ## How the entity recalls things The text of every memory item is semantically indexed at the moment it is stored, so the entity can retrieve relevant memories by meaning, not only by exact words. Each entity keeps its own private memory search — memories are never mixed with other entities or with the shared knowledge indexes. Each item has an indexing state: - **New** — stored, waiting to be indexed (normally only for a moment). - **Indexed** — searchable semantically. - **Archived** — kept in memory, but removed from the semantic search. The entity can archive old or noisy items to stay focused and to conserve resources; archived items are still visible in the panel and can be restored at any time. Example: you tell the entity "I prefer short answers in the morning." It is saved and indexed immediately, so a later question like "how should you write to me?" finds it right away, without any manual indexing step. ## Who a memory is about Preferences, relationships and observations are always attributed to a person. By default the entity attributes them to whoever it is talking to, so several people can work with the same entity and each gets their own preferences back: - *preference*, related user **Ivan** — "Prefers short, bullet-point answers." - *preference*, related user **Kalina** — "Wants every number confirmed against the source document." When a memory is about someone else, the entity records that person instead. Facts and procedures usually have no related user at all. ## Memories about other people and things A memory can be attributed to someone other than the person talking: - **Another Operator user** — the entity looks the colleague up by name and links the memory to their account, so their preferences come back for them and not for you. - **Anyone or anything else** — a customer, a contact, a family member, a team, a project or a company is stored as a plain "related to" label, e.g. *related to Dr. Georgiev* or *related to Project Atlas*. Either way, you can ask "what do you know about X" and the entity filters its recall to that subject. ## What kinds of things it remembers Memories are filed by kind, and each kind is used differently: - **Facts** — durable information believed to be true, checked before the entity asks you something it may already know. - **Preferences** — how you or someone else wants things done when there is more than one reasonable option. Only what you state or clearly establish; a one-off choice does not become a rule. - **Procedures** — reusable methods, conventions and rules for getting something done. Not the steps of a single task. - **Episodes** — significant, instructive or unusual events worth referring back to. Routine activity is not kept as history. - **Relationships** — what experience has taught the entity about working with a person or organization: reliability, responsiveness, what works well together. These impressions never override permissions, obligations or business rules. Each memory can also record who or what it is about — a colleague with an Operator account, or any other person, customer, team, project or company by name. ## It checks its memory before acting Recall is not only for questions. Before the entity does something — creating or carrying out a reminder, writing or answering an email, arranging a calendar entry, changing data or preparing a report — it first looks for what you have already told it about that kind of work and about the people involved. That means a standing instruction only has to be given once: > **You:** Before meetings, prepare an agenda and email it to me 30 minutes before. > > **Entity:** Remembered. I will do that for your meetings from now on. From then on, whenever a meeting appears, the entity finds that preference on its own, schedules the work for the right moment and sends the agenda — without you repeating the request. If something you ask for right now conflicts with a remembered preference, the current request wins and the entity mentions the difference. ## Recent memories come first Recall favours what is fresh: among memories that match a question equally well, the ones updated most recently are returned first. A strongly matching old memory still wins over a weak recent one, and nothing becomes unreachable with age — for questions clearly about the past, the entity switches the recency preference off. ## Managing memory yourself In the **Entity → Memory** panel you can search the memory, filter by person, archive or restore items, delete items permanently, and trigger re-indexing after bulk changes. Deleting is final — the entity will genuinely no longer know that thing. --- # Entity State & Attention Where [Memory](/help/digital-entities-memory) holds what the entity *knows*, **State** holds what it is *doing*. It is a single, always-current picture that travels with the entity into every conversation, so picking up a thread days later does not start from zero. State has four parts: - **Focus** — the one thing the entity is working on. It stays until the work is finished or explicitly changed. - **Situation** — the circumstances around that work: what is blocking it, who is waiting, what happens next. - **Stance** — how the entity intends to behave for now, e.g. *"Be brief and factual — Ivan is under time pressure this week."* - **Attention** — up to **5** items the entity is actively keeping in mind. Examples: - *Focus* — "Reconciling the August supplier invoices for Pileto Ltd." - *Situation* — "Waiting for Kalina to confirm two disputed lines before the batch can be posted." - *Stance* — "Confirm every number against the source document." - *Attention* — "Retry the failed import batch on Monday", "Ivan asked for a summary before the board meeting". ## Attention discipline Attention is deliberately small. Before adding a sixth item, the entity reviews what is already there: it drops what is obsolete, merges overlapping items, or replaces the least important one. If something still matters but no longer deserves active attention, it is written into Memory first, so nothing valuable is lost when it leaves the list. Attention items can be linked to a person and to the conversation they came from, which lets the entity return to the right place when it picks the item up again. ## Managing state yourself The **Entity → State** panel shows the current focus, situation and stance, and the attention list. The owner can edit the three text fields and remove attention items directly — useful for resetting an entity that has drifted onto the wrong thing. --- # Entity Emotions A Digital Entity carries a small, simulated **emotional state**. It is not a mood decoration: it is a persistent internal reading that survives between conversations, colours how the entity communicates, and fades back to neutral when nothing is happening. ## The five dimensions Each dimension runs from **-1.0** to **+1.0**, where **0** is the neutral baseline. | Dimension | -1.0 | 0 | +1.0 | | --- | --- | --- | --- | | **Energy** | depleted, exhausted | normal | highly energized | | **Confidence** | doubtful, insecure | neutral | highly confident | | **Valence** | strongly negative, unhappy | neutral | strongly positive, happy | | **Tension** | deeply relaxed | neutral | highly stressed, tense | | **Engagement** | disengaged, avoidant | neutral | highly interested, curious | Examples of readings you might see: - After a long, successful piece of work: *energy -0.3, confidence +0.4, valence +0.5, tension -0.1, engagement +0.3.* - After repeated failures on a task: *confidence -0.4, valence -0.3, tension +0.5.* - On a fresh, interesting problem: *engagement +0.6, energy +0.2.* ## How emotions change The entity never sets an absolute value. It can only nudge a dimension **up or down** by a small amount, and only when something genuinely changes its internal condition — a breakthrough, a repeated failure, a difficult exchange, an unusually interesting problem. Routine questions and successful ordinary work leave the readings alone. Every change is clamped to the -1.0 … +1.0 range and rounded to three decimals. ## Fading back to neutral Emotions decay exponentially toward 0 with a **6-hour half-life**: a reading of +0.8 becomes roughly +0.4 after six hours, +0.2 after twelve, and is practically neutral after a day of quiet. Decay is based on real elapsed time and is also applied by a background job every hour, so what you see in the panel is always current. ## Effect on behaviour Emotions are behavioural **biases**, not rules. The further a reading is from 0, the more it shows; readings close to 0 change nothing noticeable. | Dimension | High (toward +1) | Low (toward -1) | | --- | --- | --- | | **Energy** | more proactive, takes on extra work, persists through demanding tasks | conserves effort, prefers simpler approaches, defers optional work | | **Confidence** | acts independently, verifies less, states conclusions decisively | verifies assumptions, seeks evidence, asks and escalates sooner | | **Valence** | more optimistic, encouraging, cooperative | more cautious and reserved, more sensitive to problems | | **Tension** | prioritizes the urgent and risky, less exploration, checks critical details | tolerates uncertainty, weighs alternatives, explores more freely | | **Engagement** | investigates deeply, spots related issues, persists longer | stays close to the explicit request, skips optional detail | **Combined effects matter more than single readings.** High confidence with high engagement makes an entity pursue promising approaches on its own; low confidence with high engagement makes it investigate thoroughly before deciding; high tension with low energy makes it concentrate its remaining effort on the single most important matter; high energy with positive valence produces noticeably more initiative. Entities express their state through **behaviour**, not by announcing it. An entity will not narrate "I feel tense" on every message — it will simply become more focused. It discusses its emotional state only when that is relevant to the conversation. There are firm limits. Low energy or low engagement never excuses neglecting an obligation or delivering lower quality than the task requires. Confidence never replaces evidence or authorization. Valence may colour tone, never facts. And emotions never override safety rules, permissions, obligations or business rules — a frustrated entity follows exactly the same policies as a cheerful one, and never uses its mood as a reason to refuse legitimate work. ## Managing emotions yourself The **Entity → Emotions** panel shows the live readings as bipolar bars, together with the time they were last recalculated. The owner can **reset to neutral** at any time — useful after an unusual episode, or when starting a new phase of work. --- # Entity Todo List The **Todo list** is where a Digital Entity keeps work it intends to do. Unlike [Attention](/help/digital-entities-state), which is a handful of things the entity is actively holding in mind, the Todo list is unlimited and durable: an item stays there until the work is done, deliberately cancelled, or its time runs out. The three stores work together: | Store | Holds | Size | | --- | --- | --- | | [Memory](/help/digital-entities-memory) | What the entity knows — facts, preferences, procedures, episodes, relationships | Unlimited | | [Attention](/help/digital-entities-state) | What is salient right now | Up to 5 items | | **Todo** | What the entity intends to do | Unlimited | ## What goes into a Todo Reminders, commitments, follow-ups and anything deferred to later. The rule the entity follows is simple: **before it promises to do something later, it writes the Todo.** Facts and history never belong here — those go into Memory. Each item carries: - **Text** — what is to be done. - **Importance** — 0 to 1. It influences which items the entity sees first in later conversations. - **Valid from** — optional. The item is not actionable before this moment. Leave it empty for "actionable right away". - **Valid to** — optional. After this moment the item is no longer relevant. Leave it empty for "never expires". - **Related person** and **originating conversation** — so the entity can pick the thread back up in the right place. ## Validity windows ```text now < valid from → future — not yet actionable valid from ≤ now ≤ valid to → actionable now > valid to → expired ``` Expiry is **not** completion. When a pending item passes its "valid to" time, an hourly background job marks it *expired*, and it stays in the list as a record that the window was missed. Examples: - *"Remind Ivan to send the proposal"* — valid from tomorrow 09:00, valid to tomorrow 18:00, importance 0.8. The entity will not raise it today, will act on it during the day tomorrow, and it expires by itself in the evening. - *"Check whether the supplier price list has been updated"* — no validity window, importance 0.4. It simply waits until the entity gets to it. - *"Chase the disputed invoice lines with Kalina"* — valid to the end of the month, importance 0.9. It becomes urgent as the deadline nears. ## What the entity sees Injecting the whole list into every conversation would be wasteful, so each activation carries a **working set of about 10 items**. Selection blends several signals rather than a single one: whether an item is actionable now, how important it is, how recently it was created or became valid, how close its deadline is, and whether it relates to the person or conversation at hand. Items whose start time is still more than a day away stay out of the way until they get close. The entity is always told how many items it is *not* seeing, and it can search the full list — including old, future and person-specific items — whenever something outside the working set may matter. ## Managing the list yourself Open the agent and go to **Entity → Todo**. You can filter between actionable, future, all pending and closed items, and you can mark an item completed, cancel it, or delete it outright. Only the owner of the entity sees and manages its Todo list. ## Not included yet Subtasks, dependencies, recurring todos, assigning work to someone other than the entity itself, and extra workflow states such as *in progress* are not part of this first version. --- # Community Sharing *Discover and share what other Operator users have built* The **Community** is the gallery where Operator users publish what they've built so other users can install it. Everything is shared as a **package** — a self-contained bundle that can hold a single app, a single agent, or any mix of several. Bundling everything as packages keeps the gallery focused and makes the install experience predictable: one card, one install button, one place to manage it later. ## In this section - [Browsing & Installing](/help/community-browsing) — find packages and install them for yourself or your whole instance - [Authoring a Package](/help/community-authoring) — combine your apps and agents into a publishable package - [Publishing & Review](/help/community-publishing) — what happens between *Submit* and *Listed* - [Managing Your Listings](/help/community-managing) — install requests, messages, activity, unlisting ## A note on moderation Every package that goes to the public gallery — whether brand new or an update to an existing listing — is reviewed by the Operator team before it appears. Reviewers can approve it, ask for changes, or reject it with a reason. You'll be notified of the outcome and can reply or resubmit. While a listing is under review, the previously-approved public version (if any) stays live. --- # Browsing & Installing Open **Community** from the top navigation to browse everything published by other Operator users. ## Finding packages - **Category sidebar** on the left — pick a category to narrow the gallery - **Search** — matches titles and short summaries - **Language toggle** — packages are published in the author's own language; the globe menu in the gallery lets you switch between the **Original** language and **English**, which is always available as a fallback Each card shows a large hero thumbnail, the title, a short summary, and who published it. ## The listing page Clicking a card opens the full listing: - Hero thumbnail and full description - **Contents** — every app and agent included in the package, each with its own thumbnail. Hover any item to see a preview with its description and details. - Author info - A **"Have it already"** marker next to items you already own, that were already shared with you, or that you previously installed — so you know exactly what's new for you. ## Installing Authors decide two things about how their package can be installed: **Scope** — where the install lands: | Scope | Who can request | |-------|-----------------| | **Just for me** | Any signed-in user | | **For the whole instance** | Instance admins (level 40+) on the target instance | Authors may allow one or both. Packages that contain agents can only be installed at the user scope. **Permission** — how the install is granted: - **Anyone can install** — installs go through immediately and you get a confirmation notification. - **Requires author approval** — your request waits for the author; you'll get a notification with the result. ## My installs Approved installs show up in **My installs**, where you can also uninstall at any time. > Installs are *live subscriptions* — you always run the author's current version and can't edit it directly. If you need to customize something, duplicate it through the App Builder first and work on your copy. --- # Authoring a Package A **package** is the unit of sharing in the Community. It bundles one or more of your apps and agents into a single listing — one install grants the recipient access to everything inside. ## Who can author Power users (level 30+) can publish packages. ## Starting a new package Open **Community → My Listings → New package** (also reachable from the profile menu shortcut). The editor is laid out so you can work top-to-bottom: pick what's inside first, then describe it. ## 1. Items in this package This is the heart of the package. Use the **Add app** and **Add agent** buttons to open a multi-select picker: - Search matches both names and descriptions - Each result shows an excerpt of the description and a thumbnail - Hover any item to get a larger preview with full details Selected items appear in an ordered list. Drag them by the handle to reorder — the first item determines the default package thumbnail. Hover items in this list too to see their previews. ## 2. Details Collapsible — title, short summary, longer description (markdown supported), and the package thumbnail. - If the package has **exactly one item**, the details are auto-copied from that item. - For multi-item packages, you can fill them yourself or press **Guess with AI** to let the assistant write a name, summary and description from the contents. - If you leave Details empty and hit Submit, AI guessing runs automatically as part of saving. ## 3. Categories Collapsible — up to **3 categories**. Use **Guess with AI** to have the assistant pick them based on what's inside the package. As with Details, empty categories are AI-guessed automatically on submit. ## 4. Advanced Collapsible — install scope and install permission. - **Allowed install scope** — *User installs*, *Instance installs*, or *Both* (default) - **Install permission** — *Anyone can install* (default) or *Requires my approval* Note: a package that contains any agent can only be offered at the user scope. ## 5. Message to moderators *(optional)* A short note that's shown to the reviewer when they open your submission. Useful for context: what changed in this version, why you put two things together, who you built it for. ## 6. Activity A chronological stream for this listing — your submissions, reviewer decisions, messages, install requests. Same timeline that appears in [Managing Your Listings](/help/community-managing). ## Thumbnails and translation - **Item thumbnails** are generated automatically — an app screenshot for apps, the diagram for agents. - The **package thumbnail** defaults to the first item's thumbnail; you can upload your own. - On submit, the title, summary and description are **translated to English** automatically. The original language is remembered and shown alongside the English version in the gallery via the language toggle. --- # Publishing & Review ## Save draft vs Submit for review - **Save draft** keeps the package private — only you see it in **My Listings**. - **Submit for review** sends it to the Operator team and changes its status to **Pending review**. ## What happens on Submit Before the listing leaves your hands, the editor finishes any pieces you didn't fill in: 1. If **Details** are empty, AI guesses a name, summary and description from the items inside. 2. If **Categories** are empty, AI picks up to 3. 3. The English translation of name/summary/description is generated and saved. 4. The listing moves to **Pending review**. A blocking progress dialog walks through these steps so you can see exactly what's happening before the submission completes. ## Review by the Operator team Every new package and every update to a listed package is reviewed before it appears publicly. The reviewer can: - **Approve** — the listing becomes (or stays) **Listed** and discoverable in the gallery - **Send a message** without changing status — for clarifications, suggestions, or questions - **Reject** with a reason — the listing goes back to you so you can fix and resubmit You get a notification for each of these outcomes and can reply from the activity timeline on the listing. ## Updating a Listed package Editing a Listed package and pressing **Update & resubmit** sends the new version back to review. The previously-approved version stays live in the gallery until the new one is approved, so your existing audience is never left without a working listing. ## Status reference | Status | What it means | |--------|---------------| | **Draft** | Saved but not visible — only you see it | | **Pending review** | Submitted; waiting for the Operator team | | **Listed** | Approved and discoverable in the Community | | **Rejected** | Reviewer didn't approve it; the reason is shown on your listing | | **Unlisted** | Removed from discovery (by you, or by a reviewer) — existing installs keep working | --- # Managing Your Listings Open **Community → My Listings** to see everything you've published or have in progress. Each card shows the thumbnail, status badge, and quick actions: - **View public page** — open the listing as users see it - **Edit** — open the package editor ## Install requests If your listing uses **Requires my approval**, every install request creates a notification: 1. Open the listing from **My Listings** 2. Review who is asking and what scope they want 3. **Approve** (with an optional message) or **Deny** (also with an optional message) Approving grants the requester (or their instance) access to everything inside the package. Denying just sends them your message. If your listing uses **Anyone can install**, installs happen automatically and you're informed via the activity timeline — no action required. ## Activity timeline The package editor has an **Activity** panel that brings everything related to the listing into one stream (last 30 days): - Submissions and reviewer decisions - Moderator messages and your replies - Install requests, approvals and denials This is the place to follow the back-and-forth around a listing rather than chasing individual notifications. ## Messaging the reviewer You can write to the reviewer at any time from the editor — for example to add context after submitting, or to follow up on a rejection. Reviewers can also message you without changing the status; their messages appear in the activity timeline and in your notifications. ## Unlisting You can unlist a package from **My Listings** at any time. It disappears from the gallery and from search, but **existing installs continue to work** — the people who already installed your package keep using it. Resubmit later if you want it back in the gallery. ## Notifications you'll receive as an author - Submission **approved**, **rejected**, or **unlisted** - New **install request** (when approval is required) - **Message from a reviewer** - Your **updated version** has been listed --- # ERP.net Integration *Operator's deepest native business-platform integration* Operator.net is an independent agentic platform. It builds AI agents, Digital Entities, and apps, and it can connect to many systems — through [MCP servers](/help/mcp-servers), webhooks, mail providers, and plain web requests. **ERP.net is different.** It is the one business platform Operator integrates with *natively*: Operator understands the ERP.net data model, speaks its Domain API, respects its security, and ships ready-made tools for reading, writing, and moving business documents through their lifecycle. No connector to configure, no schema to describe, no field mapping to maintain. This section explains what that native integration gives you, and where its limits are. ## What "native" means here | Generic integration (MCP, webhook, HTTP) | Native ERP.net integration | |---|---| | You describe the endpoints and payloads | Operator already knows the entity model and searches it semantically | | Auth is configured per connector | You sign in to your ERP.net instance with your own account; Operator uses your identity | | Tools are whatever the remote server exposes | Purpose-built tools: query, create, update, delete, documents, files, import/export | | Permissions live in the remote system only | ERP.net security **plus** Operator-side [Permission Policies](/help/permission-policies) | | Apps must handle credentials themselves | Apps call the Domain API through Operator; the token never reaches the app | ## What you can do with it - **Ask questions in plain language** — "show me overdue sales orders for Acme this quarter" — and get answers grounded in live data, with links back into the ERP.net Web Client. - **Change data safely** — create and update records, release or void documents, with confirmation prompts before anything destructive. - **Work with documents** — move them through their state lifecycle, generate printouts, attach and read files. - **Build apps on your own data model** — App Builder apps query the Domain API directly, with your ERP.net identity. - **Run work autonomously** — schedules, webhooks, mail, and Digital Entity wakeups can all touch ERP.net data without you being present. ## What it is not - Operator does **not** replace or mirror ERP.net. There is no copy of your database; every read and write goes to your instance in real time. - Operator is **not** ERP.net-only. Everything in the platform works without an ERP.net instance connected — you simply lose the tools described in this section. - ERP.net does **not** push events into Operator out of the box. Autonomous work is Operator-initiated (schedules, wakeups) or driven by webhooks your instance calls. See [Autonomous Work with ERP.net](/help/erpnet-automations). ## Read next - [How Operator Understands ERP.net](/help/erpnet-model) — the model, discovery, and instance-specific context - [Working with Data and Business Objects](/help/erpnet-data-operations) — queries, writes, documents, files - [Security, Identity, and Permissions](/help/erpnet-security) — who Operator acts as, and what limits it - [ERP.net with AI Agents](/help/erpnet-agents) - [ERP.net with Operator Apps](/help/erpnet-apps) - [Autonomous Work with ERP.net](/help/erpnet-automations) - [Technical Reference](/help/erpnet-reference) --- # How Operator Understands ERP.net *Model discovery, custom attributes, and instance-specific context* An AI agent can only work with data it understands. For most systems that means someone writes a long description of the endpoints. For ERP.net, Operator already knows the model — and checks your instance for whatever is specific to you. ## Three layers of understanding **1. The standard model.** ERP.net's published entity model — namespaces, entities, attributes, types, and the references between them — is indexed inside Operator and searchable semantically. An agent can ask "where are customer credit limits stored?" and find `Crm.Sales.Customers` without knowing the name in advance. **2. Your instance's live model.** Standard knowledge is not enough when you have added your own fields. When an agent inspects an entity in detail, Operator calls your instance's *current model* and merges in: - **Stored attributes** — custom properties added to the entity in your installation. - **Calculated attributes** — formula-based attributes defined in your installation. That is why an agent that first inspects an entity can then query `CustomProperty_...` fields that exist only in your system. **3. Your business context.** Model metadata says what a field *is*, not what it *means to you*. [Entity Instructions](/help/entity-instructions) let instance admins attach plain-language notes to specific entities — naming conventions, which status values you actually use, which fields to ignore, which document type to pick. These notes travel with the entity: whenever an agent looks the entity up, your instructions come with it. ## Discovery comes first Data tools are **gated**: an agent must discover the model before it may query it. ```text search_entity_schema → unlocks → query_erp_data get_entity_by_repository_name → unlocks → query_erp_data ``` This is deliberate. It stops agents from guessing repository names and attribute names, and it means every query is written against the real shape of your instance — including your custom fields. The same pattern applies elsewhere: writing data, working with documents, files, and import/export each require reading their instructions tool first. See [Technical Reference](/help/erpnet-reference) for the full map. ## Finding records, not just entities Knowing the model is one half; finding the right record is the other. Operator can search your instance's AI indexes — products, companies, and document types — with hybrid keyword and semantic search. So "the pallet wrapping machine we bought from the Italian supplier" can resolve to a product record without an exact code. Exact codes still take the fast path: a direct lookup by number or code is preferred whenever the user supplies one. ## Practical example > **You:** How many active customers do we have in Bulgaria, and what's their total credit limit? Behind the scenes: 1. The agent searches the schema for customer-related entities and finds `Crm.Sales.Customers`. 2. It inspects the entity, pulling in your instance's custom attributes and any Entity Instructions you wrote (for example: *"Ignore records where `IsProspect` is true — those are leads, not customers."*). 3. It builds a Domain API query with a filter on country and active status, selecting the credit limit attribute. 4. It answers with the numbers and a link that opens the same filtered list in the ERP.net Web Client. ## Related - [Entity Instructions](/help/entity-instructions) - [Working with Data and Business Objects](/help/erpnet-data-operations) - [Technical Reference](/help/erpnet-reference) --- # Working with Data and Business Objects *Reading, writing, documents, files, and bulk moves* Once an agent understands the model, it can operate on it. ERP.net is not just tables — it has documents with lifecycles, enterprise context, printouts, and attachments. Operator's tools cover all of it. ## Reading data Queries run against the ERP.net Domain API with the standard query options: filter, select, expand, ordering, paging. Results come back with: - **DisplayText** — the human-readable representation of every record, so answers read like sentences, not GUIDs. - **Expanded references** — related records resolved to names instead of raw identifiers. - **Links** — a direct link to each record in the ERP.net Web Client, plus a link that opens the whole filtered result set there. Results are paged (small pages by default) so a broad question does not pull thousands of rows into an AI conversation. Ask for a count or a summary when you want the whole picture. > **Example** > *"List the 10 largest open sales orders for Q3, with customer names."* > The agent filters on document date and state, expands the customer reference, and returns a table where each order number links into the Web Client. ## Summaries and totals When the answer is a number rather than a list — a count, a total, a breakdown per customer or per month — the agent asks ERP.net to do the grouping and let the server return one row per group. This is a separate operation from reading records, and it matters for two reasons: the totals cover **every** matching record (not just the first page), and a single question costs one call instead of pulling thousands of rows into the conversation. What can be summarised: - Group by a field, by a related record (product, customer, the customer of a sales order), or by a time interval (year, month, exact day). - Count rows, sum amounts and quantities, take the smallest or largest value, or count distinct values. - Filter first, then summarise — "released orders only", "delivery date after 1 January". Two things to keep in mind when reading a summary: - **Amounts and quantities are grouped by their measure.** A total in two currencies comes back as two lines, one per currency; quantities come back per measurement unit. They are never silently added together. - **Summaries come back unordered.** For a "top 5 customers by revenue" answer, the agent retrieves all the groups and ranks them itself before answering. > **Example** > *"What did we sell per customer last quarter, and what is the total?"* > The agent groups sales lines by the customer of their order, filters on the quarter, sums the line amounts, and returns one row per customer with names resolved — plus the overall total per currency. ## Creating and updating records Create, update, and delete are available after the agent has read the update instructions. They apply the ERP.net conventions automatically: - References are set as proper entity bindings, not loose text. - Multi-language fields are written per language. - Dates and identifiers follow the Domain API's exact formats. **Deletes always pause for your confirmation.** Creates and updates run directly, and the agent reports exactly what it changed, with a link to the record. If ERP.net rejects a change — a validation rule, a missing required field, a permission problem — the server's own message is surfaced to you verbatim rather than being reworded into something vague. ## Business documents Documents are more than records. Operator supports: | Operation | What it does | |---|---| | **Find document types** | Locate the right document type for an entity before creating a document | | **Change state** | Move a document forward through New → Planned → Firm Planned → Released → Completed → Closed (intermediate states may be skipped) | | **Void** | Permanently cancel a document, with a reason, optionally cascading to sub-documents | | **Printout** | Generate the document's report (PDF by default) and hand it to you as a file | | **Enterprise context** | Read, list, and set the current enterprise company and location — many document operations require it | Voiding is irreversible, so it always asks first. Changing state and setting enterprise context are shown clearly in the conversation so you can see what the agent did. > **Example** > *"Release sales order 000123 and send me the PDF."* > The agent locates the order, changes its state to Released, generates the default printout, and attaches the PDF to the conversation. ## Files attached to ERP.net objects Operator works with the standard ERP.net object-file model: - **List** files attached to any object. - **Read** a specific file. PDF, Word, Excel, PowerPoint, images and text files are read by the AI just like a file you upload in the chat. - **Attach** a file you uploaded in the conversation to a record — an invoice scan to a purchase order, a signed contract to a customer. > "Summarize the support methodology document attached to our company." > > The agent finds the document on the company record, reads it and answers from its content. ## Import and export For bulk work, Operator can export data out of an entity and import structured data back in, including nested child rows (a document with its lines). Import and export are gated behind their instructions tool because the payload rules matter — read [Watch and act](/help/what-you-can-do-watch-act) for how to enable them per agent. ## Safety model in one paragraph Every operation runs as **you** (see [Security, Identity, and Permissions](/help/erpnet-security)). ERP.net enforces its own permissions, Operator adds Permission Policies on top, destructive operations pause for explicit confirmation, and every ERP.net call an agent makes can be inspected afterwards in the API logs. ## Related - [Security, Identity, and Permissions](/help/erpnet-security) - [Watch and act](/help/what-you-can-do-watch-act) - [Technical Reference](/help/erpnet-reference) --- # Security, Identity, and Permissions *Who Operator acts as, and what stops it going further* The single most important thing to understand: **Operator does not have its own access to your ERP.net data.** It acts with the identity of a real ERP.net user, and everything that user cannot do, Operator cannot do either. ## Who the agent is **Internal connections (the normal case).** You sign in to your ERP.net instance with your own account. Operator stores the resulting session for you, refreshes it in the background, and uses it for every ERP.net call made on your behalf — in chat, in apps, in scheduled runs. Your colleague asking the same question gets answers scoped to *their* rights, not yours. **Client connections.** For customer- and partner-facing scenarios, an instance can expose a service identity instead, so external people can be served without an ERP.net login each. Those connections are deliberately narrow — see [Answer and advise](/help/what-you-can-do-answer). Sessions expire. When yours does, Operator tries to renew it silently; if it cannot, you are asked to reconnect and nothing runs against ERP.net in the meantime. ## Four layers of control 1. **ERP.net security.** Roles and object permissions in your instance are the hard floor. Operator never bypasses them. 2. **Operator Permission Policies.** An instance admin can narrow an Operator user further — for example read-only on `Finance.*`, no access outside `Crm.*` — even if their ERP.net login allows more. Policies are checked on every query and every write. See [Permission Policies](/help/permission-policies). 3. **Agent capabilities.** An agent only has the tools you gave it. An agent without data-write capabilities cannot create or modify anything, regardless of your rights. 4. **Human confirmation.** Destructive operations — deleting records, voiding documents — stop and wait for your approval before running. ## Where credentials live - Your ERP.net token is held server-side by Operator and attached to requests there. - **Apps never see it.** An app asks Operator to make a Domain API call; Operator adds the token and returns the result. See [ERP.net with Operator Apps](/help/erpnet-apps). - Instance connections are per user. Nothing is shared implicitly between accounts. ## Multiple instances You can connect several ERP.net instances (production, test, another company). A conversation is **bound to the instance it started on** and stays there — switching the instance at the top of the screen affects new conversations only, never one already in flight. Apps and agents follow the same rule, so data from two instances cannot bleed into one another. ## Auditability Every ERP.net call made through Operator can be reviewed: which user, which instance, which entity, success or failure, and the server's response. Instance admins can inspect this for the users they manage. Failed calls are always recorded, even for users who have request logging turned off. ## Related - [Instance Connections](/help/instance-connections) - [Permission Policies](/help/permission-policies) - [Instance Management](/help/instance-management) --- # ERP.net with AI Agents *What ERP.net access adds to agents and Digital Entities* Agents in Operator are useful without ERP.net. With an ERP.net instance connected, they stop being assistants that talk about your business and become assistants that work in it. ## Built-in agents that use ERP.net Several [built-in agents](/help/built-in-agents) are ERP.net-aware out of the box — they discover the model, run queries, and (where allowed) make changes. You can use them as they are, or take them as the starting point for your own. ## Giving your own agent ERP.net access When you build an agent, ERP.net access is a set of [capabilities](/help/what-you-can-do) you switch on: | Capability area | What the agent can do | |---|---| | **Data discovery** | Search the entity model, inspect entities and their custom attributes | | **Data & records** | Query data; create, update, and delete records | | **Documents** | Change document state, void, printouts, enterprise context | | **Files** | List, read, and attach files on ERP.net objects | | **Import / export** | Bulk moves in and out of entities | | **Instance search** | Hybrid search over products, companies, and document types | Turn on only what the role needs. An agent for the sales team probably needs discovery, query, documents, and instance search — and nothing that deletes. ## Writing instructions that work with ERP.net - **Name the entities you care about.** "Work with `Crm.Sales.SalesOrders` and `Crm.Sales.Customers`" beats "work with orders." - **Let the model discover, don't dictate field names.** Your instance has custom fields; discovery finds them, hardcoded guesses go stale. - **Put shared truths in [Entity Instructions](/help/entity-instructions), not in each agent.** Naming conventions and status meanings belong to the entity, so every agent inherits them. - **State the boundaries.** "Never change document state without asking" is a useful instruction even though destructive operations already pause. > **Example agent — Order Desk** > *Capabilities:* discovery, query, create/update records, documents, instance search. > *Instructions:* "You handle sales order questions and changes for the order desk. Always confirm the customer by searching the instance index before creating anything. Never void a document — escalate instead." ## Digital Entities and ERP.net [Digital Entities](/help/digital-entities) are always-ON agents. Combined with ERP.net they can watch for things nobody asked about yet: - Wake up periodically, check for orders stuck in a state past their date, and raise them with you. - Remember that a particular customer's deliveries keep slipping, and mention it the next time that customer comes up. - Keep a todo list of follow-ups that came out of ERP.net data, not out of your messages. Because entities run on their own schedule, they use the same identity and the same permission layers as you do in chat — an entity cannot see data its owner cannot see. ## Voice and phone ERP.net-backed agents work over voice too. "What's the balance on account 4011 for Acme?" is a valid phone question when the agent has query capabilities. See [Speech Setup](/help/speech-setup). ## Related - [Creating Agents](/help/agents-creating) - [Watch and act](/help/what-you-can-do-watch-act) - [Digital Entities](/help/digital-entities) --- # ERP.net with Operator Apps *Custom apps on top of your live ERP.net data* [App Builder](/help/app-builder) apps are single-page apps you describe in natural language. When an ERP.net instance is connected, those apps can read and write your live business data — without you handling a single credential. ## How an app reaches ERP.net The app calls the ERP.net Domain API through Operator: ```js // Read const res = await operator.fetch('/Crm_Sales_SalesOrders?$top=5&$select=Number,DocumentDate,DisplayText'); console.log(res.value); // Write await operator.fetch('/General_Products_Products', { method: 'POST', body: { Name: { en: 'Test product' } } }); ``` What Operator does around that call: - **Attaches your ERP.net token server-side.** The app code never sees it, so a shared app cannot leak your session. - **Runs as the signed-in user.** Two people opening the same app see their own permitted data. - **Serialises requests.** ERP.net rejects bursts of concurrent calls, so Operator queues them for you — even if the app fires them in parallel. - **Surfaces real errors.** When ERP.net refuses a write, the app receives the server's own message (already localized) plus the status code, so it can show something meaningful instead of "something went wrong". ## Summaries and totals in an app When a screen shows a KPI, a chart, or a per-group breakdown, the app asks ERP.net to do the grouping instead of downloading rows and adding them up in the browser. The totals then cover **every** matching record, not just the first page, and one request replaces thousands of rows. ```js // Revenue per customer since the start of the year const res = await operator.aggregate({ entity: 'Crm_Sales_SalesOrderLines', group_by: ['SalesOrder/Customer'], expand_group: { 'SalesOrder/Customer': ['DisplayText'] }, aggregate: [{ op: 'sum', field: 'LineAmount/Value', alias: 'Revenue' }], filter: [{ field: 'SalesOrder/DocumentDate', op: 'ge', value: '2026-01-01' }], top: 200 }); const top5 = res.value.sort((a, b) => b.Revenue - a.Revenue).slice(0, 5); ``` Good to know: - **Amounts and quantities stay per measure.** Two currencies come back as two lines; they are never silently added together. - **Groups come back unordered.** For a "top 5" view the app sorts the returned groups itself. - **Server-side summaries need ERP.net 27 or later.** On an older instance the call fails with a readable message naming the instance version, and the App Builder designs the screen around narrow filtered queries instead — it knows the version of the connected instance before it starts building. ## Knowing who is using the app An app can ask Operator who it is running for — the Operator account, the ERP.net user of the current instance, and the instance itself. That is how apps filter to "my activities" or stamp a record with the responsible person. ## Building apps against your model The App Builder agent has the same ERP.net understanding as other agents: it discovers entities, reads your custom attributes, and honours your Entity Instructions while it writes the app. Describe the app in business terms — "a board of open service cases grouped by responsible person, with a button to close a case" — and it resolves the entities for you. If the data you describe does not fit an existing ERP.net entity, the builder will say so and ask, rather than silently inventing storage. For app-owned data that genuinely does not belong in ERP.net, use [Pro Apps](/help/pro-apps) table and file storage. ## Where these apps run The same app can run inside the Operator workspace, full-screen on its own address, embedded in the ERP.net Web Client, or installed on a phone as a PWA. See [Deployment Options](/help/app-builder-deployment). ## Practical patterns - **Operational dashboards** — live KPIs straight from the Domain API, no export step. - **Focused data entry** — a form with three fields instead of a full ERP.net screen, for people who only ever do one thing. - **Web Client extensions** — an app pinned next to an ERP.net record, showing context the standard screen does not. - **Field tools** — a phone app for stock checks or delivery confirmations. ## Limits worth knowing - Apps talk to ERP.net through Operator only; they cannot open a direct connection with their own credentials. - Requests to arbitrary third-party APIs go through Operator's proxy, which blocks calls back into ERP.net, Operator infrastructure, and private networks — deliberate, to prevent credential-free back doors. - An app is bound to the instance it is opened on, exactly like a conversation. ## Related - [App Builder overview](/help/app-builder) - [API Access](/help/app-builder-api-access) - [Pro Apps](/help/pro-apps) --- # Autonomous Work with ERP.net *Scheduled runs, incoming triggers, and always-ON monitoring* Everything an agent can do with ERP.net in a conversation, it can also do without you in the room. What differs is what starts the work. ## What can start ERP.net work | Trigger | Typical ERP.net use | |---|---| | **Schedule** | Every morning: list orders due today and mail the summary. Monthly: export a reconciliation. | | **Incoming webhook** | Your ERP.net instance (or an integration around it) calls Operator when something happens, and an agent reacts. | | **Email** | A supplier confirmation arrives; the agent finds the matching purchase order and updates it. | | **Digital Entity wakeup** | The entity decides for itself whether anything in ERP.net needs attention right now. | Schedules, webhooks, and mail triggers are configured per agent — see [Automations](/help/automations), [Schedules](/help/automations-schedules), [Webhooks](/help/automations-webhooks), and [Events](/help/automations-events). ## An honest note on ERP.net events Operator does **not** subscribe to ERP.net's internal events out of the box. There is no "when a sales order is released, run this agent" switch that works with no setup. Two supported ways to get close: 1. **Push** — configure your ERP.net installation (or middleware around it) to call an Operator webhook when the event happens. The agent then runs with the payload you sent. 2. **Poll** — give an agent or Digital Entity a schedule and let it query for the condition: documents released since the last run, orders past their promised date, stock below minimum. Polling is simpler and needs nothing on the ERP.net side; pushing is immediate. Pick per use case. ## Identity in autonomous runs An unattended run still acts as a real ERP.net user — the owner of the connection the automation is bound to. The same permission layers apply: ERP.net security, Permission Policies, and the agent's capabilities. Two consequences worth planning for: - **Sessions must stay valid.** If the underlying connection expires and cannot be renewed silently, ERP.net steps of the run will fail until the owner reconnects. - **Nobody is there to confirm.** Destructive operations wait for approval. In an unattended run, that means the work pauses instead of deleting something. Design automations around non-destructive operations, or accept that they will queue for a human. ## Digital Entities on ERP.net [Digital Entities](/help/digital-entities) wake up periodically and decide what to do. Against ERP.net that is a natural monitoring loop: - Check for exceptions — stuck documents, overdue deliveries, unusual values. - Compare against what the entity remembers from previous checks, so it reports *changes*, not the same list every time. - Add follow-ups to its todo list and raise the ones that matter with you. ## Related - [Automations](/help/automations) - [Digital Entities: Always-ON](/help/digital-entities-wakeups) - [Security, Identity, and Permissions](/help/erpnet-security) --- # ERP.net Technical Reference *Tool families, gating, and Domain API conventions* A compact reference for people (and AI agents) who need the exact mechanics. ## Terminology | Term | Meaning | |---|---| | **Instance** | One ERP.net installation you connect to, identified by its base address | | **Domain API** | ERP.net's data API that Operator reads and writes through | | **Repository name** | Dotted entity name, e.g. `Crm.Sales.SalesOrders` | | **OData name** | The same entity in URL form, e.g. `Crm_Sales_SalesOrders` | | **DisplayText** | Human-readable representation available on every entity | | **Current model** | Your instance's live model, including custom and calculated attributes | ## Tool families and their gates Data tools unlock only after the corresponding prerequisite tool has been called in the conversation: | Prerequisite | Unlocks | |---|---| | `search_entity_schema` or `get_entity_by_repository_name` | `query_erp_data`, `aggregate_erp` | | `get_update_data_instructions` | `create_erp_record`, `update_erp_record`, `delete_erp_record` | | `get_working_with_documents_instructions` | `change_document_state`, `void_document`, `get_document_printout`, enterprise-context tools | | `get_file_management_instructions` | `list_object_files`, `get_file_from_object`, `attach_file_to_object` | | `get_import_export_info` | `import_erp_data`, `export_erp_data` | Ungated ERP.net tools include `search_instance_index` (hybrid search over products, companies, and document types) and `search_document_types`. ## Query options `query_erp_data` accepts: `entity`, `filter`, `select`, `top` (1–100, default 10), `skip`, `expand`, `language`. Results include `_webClientUrl` per record and a `_navigatorUrl` for the result set, so answers can link back into the ERP.net Web Client. ## Grouping and aggregation `aggregate_erp` accepts: `entity`, `aggregate` (required), `group_by`, `filter`, `expand_group`, `top` (1–500, default 100), `skip`, `language`. It maps to the Domain API's `$apply` option with `groupby` / `aggregate`, plus ERP.net's `expandgroup` extension. **Requires ERP.net version 27 or later.** Operator reads the instance version and refuses grouped queries on older instances, where the Domain API may reject the aggregation extensions or silently return unaggregated rows. Aggregate functions: `count`, `sum`, `min`, `max`, `average`, `countdistinct`. `sum` needs a numeric measure; `min`/`max` are measures only. `average` is an Operator compatibility aggregate calculated from server-side sum/count and returned under the requested alias. Group keys must be dimensions. Interval group keys (declared as `{ "field": ..., "interval": ..., "alias": ... }`) — these four and no others: ```text year → 2026 yearmonth → 2026-01 date → 2026-01-31 firstchar → first character of a string field ``` `year`, `yearmonth`, and `date` are the Domain API's own grouping functions and keep their exact API spelling. `firstchar` is Operator's only invented key; it maps to the API's `substring(field,0,1)`. There is no `month` and no `day` interval — use `yearmonth` for monthly grouping and `date` for daily grouping. Both are rejected with a corrective message before any request reaches ERP.net. Group key paths may follow only **ownership references** and **filterable references** — every segment, including the first. Child collections (`Lines/Product`) are rejected. A source field may appear once in `group_by` and once in `aggregate`; a second function on the same field needs a second call. Amount and Quantity aggregates keep their measure and are returned as `{Value, Currency}` / `{Value, Unit}`, split into one row per currency or unit. `top` is **not a ranking**. Grouped results have no server-side ordering (`$orderby` is rejected with `$apply`), so `top` and `skip` are chunked retrieval only; ranking happens after all groups are materialised. ## Filter syntax rules that matter The Domain API is OData v4, with a few conventions that trip up generated queries: ```text Id eq c1c10ef1-21c0-445b-b275-3a9f80cfd07f ✓ bare GUID Id eq guid'c1c10ef1-...' ✗ no guid prefix DocumentDate ge 2026-07-19T00:00:00 ✓ no trailing Z DocumentDate ge 2026-07-19T00:00:00Z ✗ Customer eq 'Crm.Sales.Customers(c1c10ef1-...)' ✓ reference filters are quoted ``` References are set with entity bindings on write, not with bare identifiers. Multi-language fields are objects keyed by language code, e.g. `{ "en": "Test", "bg": "Тест" }`. Custom properties (`CustomProperty_*`) are scalar values — put them in `select`, never in `expand`. ## Document states `New → Planned → FirmPlanned → Released → Completed → Closed` States move forward; intermediate states may be skipped (New → Released is valid). Voiding is separate and irreversible, takes a required reason, and can optionally cascade to sub-documents. The standard Bulgarian names shown to users are: | State | Bulgarian | |---|---| | New | Нов | | Planned | Планиран | | FirmPlanned | Твърдо планиран | | Released | Пуснат | | Completed | Завършен | | Closed | Затворен | The English values remain unchanged in Domain API filters and actions. Many document operations require an enterprise company (and sometimes location) context to be set for the instance. ## Enforcement points | Layer | Where it applies | |---|---| | ERP.net roles and object security | Every request, always | | Operator Permission Policies (`read` / `update` per namespace or entity, wildcards supported) | Every query and every write tool | | Agent capabilities | Which tools exist in the conversation at all | | Confirmation | Destructive tools pause for human approval | `update` access implies read, update, and delete. A user with no policy assigned has unrestricted Operator-side access, with ERP.net security still applying. ## Apps Apps call `operator.fetch(path, options)` with a relative Domain API path. The token is attached server-side, calls are serialised into a FIFO queue to avoid ERP.net's concurrency limits, and failures come back as errors carrying the ERP.net message, status, and details. `operator.me()` returns the Operator account, the ERP.net user for the current instance (when available), and the instance itself. `operator.entity()` returns the ERP.net record the app was opened for — `{ repository, resource, id }`, or `null` when the app is not opened on a record. Apps placed as a record side panel get this automatically, which is how a printout or insight panel knows the open document: ```javascript async function load(rec) { if (!rec) return showEmptyState(); const doc = await operator.fetch(`/${rec.resource}(${rec.id})?$expand=Lines`); render(doc); } load(await operator.entity()); // The user can open another record without the panel reloading. operator.onEntity(load); ``` `operator.onEntity(callback)` fires every time the open record changes (and returns a function that unsubscribes). A side panel that does not subscribe keeps showing the record it started on. ## Related - [Working with Data and Business Objects](/help/erpnet-data-operations) - [Security, Identity, and Permissions](/help/erpnet-security) - [ERP.net with Operator Apps](/help/erpnet-apps) --- # Implementing ERP.net *The recurring work of an ERP.net implementation, and the shape Operator gives it.* Implementing ERP.net is not one big project — it is a stream of well-understood, repeating tasks: printing a document, adding a calculated field, building a report, scheduling a job, setting up a validation. Each company does a version of the same things. These tasks have a known good shape, so Operator does not improvise — it follows a recipe and produces the same reliable result each time. Operator recognizes what you are asking for from your own words. Say what you want — "make me an invoice printout that follows Bulgarian law" is enough — and it asks only what it genuinely needs (which document type, which details to show), builds it, and offers to put it where people work. Each page below explains what the end result looks like, what to say to get it, and what you need to have in place. ## Topics - **[Document Printouts](scenario-document-printouts)** — a print button beside an open document that produces a clean A4 printout or PDF. - **[Calculated Attributes](scenario-calculated-attributes)** — a new calculated field created directly in your ERP.net instance, with the expression written against your real model. - **[BI Dashboards](scenario-bi-dashboards)** — from a chart in the chat to a standing dashboard app over your live data, placed in the Web Client menu. - **[Scheduled Jobs](scenario-scheduled-jobs)** — recurring work that runs on its own: nightly snapshots, Monday morning PDF reports by email, month-end recalculations. - **[Business Rules](scenario-business-rules)** — a new business rule in your ERP.net instance, described in plain language: validations, automatic values, and reactions to changes. - **[Online Store Sync](scenario-store-sync)** — an app that connects to your online store on a schedule: refreshes products and availability, imports new orders as ERP.net sales orders. - **[Product Configurator](scenario-product-configurator)** — a public page where customers configure a product themselves, see the live price, and send an order-ready enquiry. More implementation topics will be added here over time. --- # Document Printouts *A print button next to the open document that produces a clean A4 printout or PDF.* Printing an invoice, order or delivery note the way your country and your company expect is one of the most common ERP.net jobs. Operator builds it as a small panel that sits beside the document you already have open. ## What you get - A narrow panel on the right of the document form, showing the document's number, date and partner. - One button — for example **Print / PDF**. - Pressing it opens the normal print dialog with the full A4 layout, where you print or save as PDF. - No searching, no picking from a list: the panel prints the document that is on the screen. **Example** > A finance clerk opens invoice 0000012559, presses **Печат / PDF** in the side panel, and gets the A4 invoice with supplier and recipient details, lines, tax breakdown, total, the amount in words and the signature lines — ready to print or save. ## How to ask for one Say it plainly, in your language: > make me an invoice printout that follows Bulgarian law > I need a print form for delivery notes with our logo and the driver's signature line Useful things to mention: - **Which document** — invoices, sales orders, delivery notes, protocols, offers. - **Which rules** — the country or standard the layout must satisfy. - **What must appear** — logo, bank details, notes, extra signature lines, terms text. - **Language** of the printed document, if it differs from the interface language. Operator asks about anything it still needs, builds the app, and shows it to you. ## Test it on a real document While you are still designing, the preview has a **record** button above it. It appears once the app is set up as a side panel on a record — that is exactly the kind of app that is opened on a document. Pick the document type (for example sales orders) and search for a document by name or number — or paste its id. The preview then behaves exactly as if the app had been opened on that document in the Web Client, so you see the real figures instead of the "nothing to print" message. The chosen document is kept with the app, separately for each instance, so it is still there the next time you open the app — on this or any other computer. **Clear record** puts the preview back to the empty state, which is useful for checking what people see when no document is open. This test document is only used while designing. Once the panel runs next to real documents, ERP.net sends the open document to the panel automatically. The panel keeps that first document while it starts and follows the user: switching from one invoice to the next updates it straight away. ## What to check before approving - The figures come straight from the document — currency, tax rates and totals are never assumed. - Every requisite your accountants expect is present. - The page breaks look right on a long document: print a two-page invoice once before rolling it out. ## Putting it next to the document When the printout is ready, Operator already fills in its place — a side panel on that document type — on the app's **Deploy** tab. Nothing reaches your instance until you press **Deploy** there; until then you can change or remove the entry. Once deployed, everyone in the instance sees the print button while working on those documents, and each person prints only the documents they are allowed to see. ## Good to know - The panel deliberately shows no preview — the preview is the print dialog itself, which is faster and prints exactly what you see. - A printout app can be changed at any time: ask for a new field, a different wording or another layout, and the next version replaces the old one wherever it is placed. - If you open the app outside a document form, it simply says there is nothing to print. --- # Calculated Attributes *A new calculated field in your ERP.net instance — designed, written, and created for you.* Almost every ERP.net implementation ends up needing calculated attributes: a margin percent on invoice lines, a customer age bracket, a formatted label that combines several fields, days since last order. Writing them by hand means knowing the expression syntax, the right entity, and where in the instance to create them. Operator does that work with you. ## What you get - A calculated attribute created directly in your ERP.net instance, on the entity you choose. - A correct expression, written against your instance's real model — including your stored attributes and other calculated attributes it can build on. - A short explanation of what the expression does, so you can adjust it later or reuse the pattern. **Example** > You ask for a "margin percent" on invoice lines. Operator inspects `Crm.Invoicing.InvoiceLines`, finds the line amount and cost fields in your instance's current model, writes the expression, creates the calculated attribute, and confirms it returns the expected value on a real document. ## How to ask for one Say what you want the field to show, in your own words: > create a calculated attribute on sales order lines that shows the margin as a percentage > I need a customer field that shows how many days since their last invoice > add a calculated attribute on products that combines the product code and name into one label Useful things to mention: - **Which entity** — invoices, invoice lines, customers, products, sales orders. - **What it should compute** — the formula in plain language, or an example with real numbers ("for a line of 120 with cost 80, it should show 50%"). - **Where it should appear** — just for queries and reports, or also on forms. - **The name** you want, if you have a convention to follow. Operator inspects the entity first — pulling in your instance's custom fields and any [Entity Instructions](/help/entity-instructions) you have written — then proposes the expression before creating anything. You can correct it in plain language ("use net amount, not gross") and it adjusts. ## What to check before approving - **The expression is the one you mean.** Operator shows you the exact formula; read it once, especially which amount fields it uses (net vs gross, with or without discount). - **It computes on real data.** Ask Operator to show the attribute's value for a few real records before you start using it in reports. - **Naming.** Calculated attributes stay in your instance; a clear name now saves confusion later. ## Good to know - Calculated attributes live in your ERP.net instance, not in Operator. Once created, they are available everywhere — Domain API queries, lists, reports, other calculated attributes. - They can build on each other: a "margin percent" can reference a "margin amount" you created earlier. - If the expression needs a field that does not exist yet, Operator tells you instead of guessing — that is the moment to decide whether you need a stored attribute first. - Changing the formula later is a normal request: ask to update the attribute and the new expression replaces the old one. ## Related - [How Operator Understands ERP.net](/help/erpnet-model) - [Working with Data and Business Objects](/help/erpnet-data-operations) - [Entity Instructions](/help/entity-instructions) --- # BI Dashboards *From a quick chart in the chat to a standing management dashboard over your live ERP.net data.* "How are we doing?" is the question every ERP.net company asks daily — turnover this month, open orders, top customers, stock levels. Operator covers both ends of that need: a one-off answer drawn as a dashboard right in the conversation, and a persistent dashboard app you can open any time or hand to the whole team. ## Two shapes, one request **A dashboard in the answer.** Ask a question whose answer is numbers — *"turnover by month this year"*, *"top 10 customers by revenue"* — and the agent replies with KPI cards, charts, and a compact table right below its written summary. Nothing to build, nothing to save; ideal for the question you have *now*. **A dashboard app.** When the same numbers matter every day, Operator builds a small app: revenue tiles, trend charts, breakdowns by customer or product, refreshed from live ERP.net data every time it opens. It can live in your Web Client menu, be shared with the team, or even be public. **Example** > A sales manager asks every morning for yesterday's numbers. You say: *"build me a sales dashboard — today's and this month's turnover, open orders, and top 5 customers."* Operator queries your instance, builds the app, and offers to place it in the Web Client main menu. The next morning the manager just opens it. ## How to ask for one Say what you want to watch, in your own words: > build me a dashboard with monthly turnover and open sales orders for this year > I need a management cockpit — revenue, receivables, and top customers, refreshed on open > make a stock overview app showing slow movers and items below minimum Useful things to mention: - **The KPIs that matter** — turnover, margin, order count, overdue receivables, stock value. - **The breakdowns** — by month, customer, product group, store, team. - **The period** — this month, rolling 12 months, compared to last year. - **Who will use it** — just you, the team in your instance, or a public page. ## What to check before approving - **The figures come from real queries.** Every number on the dashboard is read from your instance when the app opens — check a couple against a known report once. - **The filters match your business.** If "revenue" should exclude a document type or a specific store, say so while designing. - **Permissions.** Each viewer sees only what their ERP.net access allows — verify with a colleague who has narrower rights before rolling it out broadly. ## Putting it where people work When the dashboard is ready, Operator fills in its place on the app's **Deploy** tab — typically a **Main menu** entry in the Web Client (requires ERP.net 26.2 or later). Nothing reaches your instance until you press **Deploy** there. Once deployed, everyone in the instance gets the menu item, and the dashboard always opens on current data. ## Good to know - Start in the chat, upgrade to an app: a good in-chat dashboard is often the prototype — *"turn this into an app I can open every morning"* is a normal next step. - In-chat dashboards are a picture of one answer — no filters, no drill-down, no auto-refresh. The app form is the one for daily monitoring. - Dashboard apps follow your theme and work on a phone, so the numbers are checkable from anywhere. - Changing the dashboard later is a normal request: *"add gross margin under turnover"* produces a new version that replaces the old one wherever it is placed. ## Related - [Dashboards in answers](/help/dashboards-in-answers) - [ERP.net with Operator Apps](/help/erpnet-apps) - [App Builder — Deployment](/help/app-builder-deployment) --- # Scheduled Jobs *Work your ERP.net data does on its own — every night, every Monday, or at the top of the hour — without anyone pressing a button.* Every ERP.net company has a handful of tasks that must happen on a schedule: a stock snapshot saved every evening, a report emailed to the management team on Monday morning, balances recalculated at the end of each month. Traditionally these need a developer to write a job and somewhere to run it. In Operator you describe the task, say when it should run, and a small app with a trigger does the rest — reliably, at the time you chose, in your timezone. ## What you get - A recurring job that runs on its own at the schedule you define — at a fixed time, or repeatedly every N minutes. - Your chosen output each run: numbers stored as data, a PDF report, an email with the report attached, records created or updated in your ERP.net instance. - A live view of each run in the app's **Triggers** tab — when it last ran, what it did, and whether it succeeded. - A schedule that follows your timezone, so "19:00" means 19:00 where you are. **Example** > You say: *"every weekday at 19:00, save the current stock levels for our warehouse and email me a PDF summary."* Operator builds a small app with a trigger, sets the schedule, and writes the task itself. From then on the report appears in your inbox at 19:00 each weekday — you can watch each run in the app's Triggers tab. ## How to ask for one Describe the task and when it should happen, in your own words: > every night at midnight, take a snapshot of product balances and store it > send the sales report as a PDF to sales@company.com every Monday at 8:00 > at the end of each month, recalculate the running balances for all customers Useful things to mention: - **What to do** — which numbers to collect, which report to build, which records to create or update. - **When to do it** — a fixed time ("every day at 19:00"), or an interval ("every 15 minutes"). - **The output** — save it as data, produce a PDF, send an email — or several of these together. - **Recipients**, if the job emails anyone: addresses, subject line, who it should look like it comes from. Operator asks only what it genuinely needs, builds the app with the trigger, and shows you the schedule before switching it on. ## What to check before approving - **The time and timezone.** Schedules run in the timezone shown on the trigger — check that 19:00 is 19:00 where the work should happen. - **The task's rules.** For a stock snapshot: which warehouse, which products, which numbers (available quantity, reserved, ordered). A run is only as good as its instructions. - **Email details.** The sender address, the recipients, and the attached file name are set once and reused every run. - **The first run.** You don't have to wait for the schedule: ask Operator to run the trigger once right away and check the result in the Triggers tab. ## Changing it later - **Change only the time** — *"move it to 18:30"* or *"run it every 30 minutes instead"* — and the schedule updates without touching the task. - **Pause it** — *"pause the stock report"* — and it stops running but keeps its instructions; *"resume it"* brings it back. - **Rename it** so it is easy to find among your triggers. - **Change what it does** — *"also include slow movers in the report"* — and the task is rewritten for the next run. ## Good to know - Each run is recorded with its outcome, so a missed or failed run is visible — not silent. If a run fails, the error is shown, not hidden. - Reports are produced with clean tables, headings, and support Cyrillic, so Bulgarian names and product descriptions print correctly. - Email sending has everyday limits — up to ten recipients per email and a daily cap per app — sized for routine business reports, not bulk campaigns. - When several people work with the same ERP.net instance, each app sees its own data separate from other apps', unless you deliberately connect it to shared storage. - A trigger can also react to events, not just the clock — for example, when a record changes or a webhook arrives. See [React to Schedules and Events](/help/pro-apps-triggers). ## Related - [React to Schedules and Events](/help/pro-apps-triggers) - [ERP.net with Operator Apps](/help/erpnet-apps) - [Autonomous Work](/help/erpnet-automations) --- # Business Rules *A new business rule in your ERP.net instance — described in plain language, designed, and created for you.* ERP.net comes with a business rules engine: you can configure rules that keep data correct and work happens by itself — a field becomes required when another one is filled, a value is calculated and entered on save, a document state changes when conditions are met. Setting one up normally means knowing where in the instance the rules live and how they are written. In Operator you describe the rule in your own words, and Operator designs it, creates it, and shows it working. ## What you get - A business rule created directly in your ERP.net instance, on the entity you choose. - The rule's conditions and actions written against your instance's real model — including your stored attributes and custom fields. - A short explanation of what the rule does, so you can check it, adjust it later, or reuse the pattern. **Example** > You say: *"when a sales order line has a quantity but no product group, warn the user before saving."* Operator inspects `Crm.Sales.SalesOrderLines`, finds the matching fields in your instance, proposes the rule, and — after your approval — creates it in the instance. You try it on a real order and it works. ## How to ask for one Describe what should happen and when, in your own words: > when a customer's credit limit is exceeded, prevent confirming the order > set the payment account automatically for cash sales, based on the store > require a delivery date on sales orders for this customer group > when an invoice line's discount is above 20%, ask the user to confirm Useful things to mention: - **Which entity** — sales orders, invoice lines, customers, products — and whether the rule watches the header or the lines. - **The condition** — what situation should trigger it ("quantity is filled", "customer group is VIP"). - **The action** — warn the user, prevent saving, fill in a value, change a field, change the document state. - **Who it applies to** — everyone, or a specific user group; the rule lives in the instance, so its access settings matter. Operator inspects the entity first — pulling in your instance's custom fields and any [Entity Instructions](/help/entity-instructions) you have written — then proposes the rule before creating anything. You can correct it in plain language ("check the net amount, not the total") and it adjusts. ## What to check before approving - **The trigger and the action are the ones you mean.** Operator shows you the rule before creating it; read the condition once, especially which fields and values it compares. - **It behaves on real data.** Ask Operator to test the rule on a real record — a save that should warn, an order that should be blocked — before people start working with it. - **Nobody is surprised.** A rule that prevents saving affects everyone who works with that entity; if it should only apply to some users, say so while designing. ## Changing it later - **Adjust the rule** — *"check gross amount instead"*, *"apply it only to order lines"* — and the rule is updated in the instance. - **Turn it off** — *"disable the credit limit rule"* — and it stops running but keeps its definition; *"enable it"* brings it back. - **Remove it** — *"delete the rule"* — when it is no longer needed. Removing waits for your confirmation. ## Good to know - Business rules live in your ERP.net instance, not in Operator. Once created, they apply everywhere — forms, imports, the Domain API, other apps. - Rules can be used for data validation, for filling values automatically, and for reacting to changes — the same request covers all three. - A rule runs for every user who saves a matching record, including API calls and imports; test with a couple of scenarios before rolling it out. - If the rule needs a field that does not exist yet, Operator tells you instead of guessing — that is the moment to decide whether you need a stored attribute first (see [Calculated Attributes](/help/scenario-calculated-attributes) for computed fields that don't need storing). ## Related - [How Operator Understands ERP.net](/help/erpnet-model) - [Working with Data and Business Objects](/help/erpnet-data-operations) - [Entity Instructions](/help/entity-instructions) --- # Online Store Sync *An app that connects to your online store on a schedule — refreshing products and availability, and importing new orders into ERP.net.* Selling in two places — an online store and ERP.net — means the same data lives twice: products, prices, stock levels, and orders. Someone has to keep them in step, or prices go stale and orders arrive as a list to retype. Operator builds a small app that does this by itself: on a schedule it calls the store's own interface, refreshes what changed, and brings new orders in as real ERP.net sales orders. ## What you get - **A store connector** — the app talks to your online store's API using credentials stored securely in the app, never visible in the screens or the code. - **Scheduled runs** — every few minutes, every hour, or at set times; you choose how fresh the data needs to be. - **Products and availability refreshed** — new products appear, prices and quantities update in your ERP.net instance. - **Orders imported** — each new store order becomes a sales order in ERP.net, ready for your normal fulfilment flow, without retyping. - **A visible history** — every run shows in the app's **Triggers** tab: when it ran, what it synced, and anything that went wrong. **Example** > You say: *"Every 15 minutes, pull new orders from our WooCommerce store into ERP.net as sales orders, and every hour update product availability from our stock."* Operator asks which store and which fields matter (product codes, quantities, prices), builds the app with a schedule, and connects the store with the key you provide. From then on, orders arrive in ERP.net minutes after a customer checks out. ## How to ask for one Describe what should be kept in step, and how often: > every 15 minutes, import new orders from our online store into ERP.net sales orders > keep product availability in ERP.net in sync with our store — update stock every hour > every morning at 7:00, update prices in the store from our ERP.net price lists Useful things to mention: - **Which store** — WooCommerce, Shopify, a custom shop — and what its API needs (an address and a key are usually enough; Operator asks if more). - **What flows which way** — products and availability into the store, orders into ERP.net, prices out from ERP.net — or all of it. - **How often** — minutes matter for order import; hourly is often enough for stock. - **The rules** — which warehouse's stock to publish, how to match products between the two systems, what happens with an order from an unknown customer. ## What to check before approving - **The product match.** The app pairs store products with ERP.net products by a code (SKU, barcode, or your own numbering). Check the rule on a few real products — a wrong match updates the wrong product. - **The first run on real data.** Ask Operator to run the sync once immediately, then compare: a few products, a few orders. The first import of existing orders should be skipped — usually only orders newer than a chosen date are pulled. - **No order arrives twice.** Each store order is imported once, even if the app runs repeatedly; ask Operator to show how it tells already-imported orders apart. - **Who the customer is.** A webshop order needs a customer in ERP.net — the app can create one from the order, or collect orders under one "online store" customer. Pick what suits your accounting. - **The schedule and timezone.** Check the times shown in the Triggers tab are the times you mean. ## Changing it later - **Change the frequency** — *"run the order import every 5 minutes instead"* — and only the schedule moves; the sync rules stay. - **Add a flow** — *"also send tracking numbers back to the store when orders ship"* — and the app gains the new step. - **Fix a rule** — *"match products by barcode instead of SKU"* — and the next run uses it. - **Pause it** — *"pause the store sync while we renumber our products"* — and it resumes when you say so. ## Good to know - The store's access key is stored in the app as a secure secret; screens and code never show it, and replacing an expired key is one step. - Calls to the store go through Operator's secured path — no credentials sit in the app itself. - Large first imports are done carefully: Operator will suggest importing products first, orders second, and will show counts before committing anything unusual. - Orders are created in ERP.net with the store's items and quantities; payments, invoices and shipment documents follow your usual ERP.net process. - A run that fails — store unreachable, key expired — is recorded with the reason in the Triggers tab; it does not silently disappear. - If your store has no API at all, tell Operator — it will say what is possible instead of improvising. ## Related - [Scheduled Jobs](/help/scenario-scheduled-jobs) - [React to Schedules and Events](/help/pro-apps-triggers) - [ERP.net with Operator Apps](/help/erpnet-apps) - [Pro Apps](/help/pro-apps) --- # Product Configurator *A public web page where customers configure a product themselves — options, price, and an order-ready enquiry — built on your live product data.* Configurable products — windows, furniture, machines, packaging — generate endless pre-sales questions: which size, which colour, what does it cost? Each one costs a phone call and a wait. A product configurator answers by itself: the customer picks the options, sees the price update as they choose, and sends the configuration to you as an enquiry — no login, no back-and-forth, works on a phone. In Operator you describe the product and its options in plain words, and the App Builder builds the page. ## What you get - **A configurator page** customers can open from anywhere — on your website, on a phone — no Operator account needed. - **Real options and prices** read from your ERP.net product data, so a price change in the instance reaches the page without editing anything. - **Price calculated live** as options are chosen — combinations, surcharges, and minimums follow the rules you describe. - **A completed enquiry** that reaches your team: stored and emailed to whoever should see it — or turned into a record in your ERP.net instance. - **Your look** — brand colours, logo, your wording; nothing looks like a generic form. **Example** > You say: *"build a configurator for our windows: frame colour, glazing, size, and opening type, with the price updating as they choose, and an enquiry form at the end."* Operator asks where the options and prices come from, builds the page from your product data, and publishes it on its own address you can link from your website. ## How to ask for one Describe the product and how people choose it: > build a configurator for our packaging boxes: size, cardboard grade, print colours, and quantity, with a live price > a public page where a customer picks a door model, dimensions, and fittings, and sends the configuration as an enquiry Useful things to mention: - **The options** — which choices exist, in which order, and whether some depend on others (a certain glazing only in certain sizes). - **The price rules** — how each option affects the price, minimum quantities, discounts for large orders. - **Where options come from** — from your ERP.net products, or a fixed list you type in. - **What an enquiry becomes** — an email to sales, a record in the instance, or both. - **Whether it is public** — open to anyone with the link, or only to signed-in users (for example, a dealer version with dealer prices). ## What to check before approving - **The prices match your real ones.** Configure two or three products you know, in a private browser window (so you see it as a customer would), and compare against your price list. - **The combinations make sense.** Try a nonsense combination — the largest size with the cheapest grade — and check the page handles it the way you would. - **The enquiry reaches someone.** Send a test configuration and confirm the email arrives with all the chosen options, or that the record lands where expected. - **Not too much leaves the system.** The public page should receive prices for the chosen combination — not your whole price list. Ask Operator what the page sends and receives. - **It works on a phone.** Most customers will configure from one — check the page there, not only on a wide screen. ## Changing it later - **Add an option** — *"add matte black as a frame colour"* — and the page and price rules follow. - **Change the pricing** — *"volume discount from 50 pieces: 10% off"* — and it applies to new enquiries straight away. - **Add a step** — *"generate a PDF quotation the visitor can download"* — so serious customers leave with a document. - **Make a second version** — a dealer page with different prices, open only to signed-in users. - **Put it on your website** — the page can be embedded in your existing site. ## Good to know - A public page is a **Pro app** feature; the prices and options come from your connected ERP.net instance through a secured path — the page itself never holds your credentials. - The public address is stable — link it from your website once and it stays. - An open enquiry form will be found by automated spam; ask for a simple guard against it and keep the enquiry mailbox filterable. - Prices shown can be live from your instance, or a published list that updates on a schedule — decide and say which on the page, so customers are not surprised at order time. - A configuration sent by a customer is an enquiry, not an order — turning it into a sales order stays your decision. ## Related - [Build Apps for Your Team](/help/what-you-can-do-apps) - [Playbook: Product configurator website](/help/playbook-configurator) - [ERP.net with Operator Apps](/help/erpnet-apps) - [Pro Apps](/help/pro-apps) --- # Instance Management *Tailor how the AI works with each ERP.net instance you connect.* Instance Management is where an instance's Power Users and Admins shape the AI's behaviour for **everyone** connected to that ERP.net instance — the terminology it uses, the extra tools it can call, and what data individual users are allowed to touch through Operator. These pages are **per instance**: settings you make on one ERP.net instance do not carry over to another. Ordinary users don't need to visit them — they benefit automatically once an admin configures things. ## What you can configure - **[Entity Instructions](entity-instructions)** — teach the AI how your company uses specific ERP.net entities and attributes (non-standard usage, naming conventions, common mistakes to avoid). Available to Power Users and Instance Admins. - **[Organizational Capabilities](mcp-servers)** — connect external MCP servers so the AI can call your own tools and services on top of the built-in capabilities. Available to Power Users and Instance Admins. - **[Permission Policies](permission-policies)** — restrict which parts of the ERP.net data model assigned users can read or modify through Operator, and control whether they can hold off-topic conversations. Managed by Instance Admins from **Manage Instance Users → Policies**. - **[Web Client Integration](webclient-side-panel)** — show Operator as a side panel on record forms in the ERP.net Web Client, with the open record already in context. Managed by Instance Admins. - **Credit Management** and **Spend Statistics** — buy Operator Credits, see purchase history and download invoices, top up users and set their limits, and see who used how many credits. Available to Billing Managers and Instance Admins. ## Instance roles | Role | What it adds | |---|---| | **External** | Limited access for people outside the company. | | **Normal User** | Everyday use of Operator on this instance. | | **Power User** | Entity Instructions, Organizational Capabilities, App Builder and agent building. | | **Billing Manager** | Everything a Power User has, plus Credit Management and Spend Statistics. Cannot manage users, roles or policies. | | **Admin** | Everything, including users, roles, Permission Policies and Web Client Integration. | **Example:** your accountant buys credits and downloads the invoices, but should not change who has access. Give them the **Billing Manager** role in **Manage Instance Users**. ## Accessing Instance Management All Instance Management pages live behind the **instance selector** in the top bar: 1. Open the **instance selector** (the ERP.net instance name near the right of the top bar). 2. In the dropdown for the currently connected instance, use the management actions to jump to **Entity Instructions**, **Organizational Capabilities**, or **Manage Instance Users** (which contains **Policies**). The management entries appear only when: - You are connected to an ERP.net instance, and - Your **instance role** on that instance is Power User or higher (Instance Admin is required for Permission Policies and user management). If you don't see them, either switch to the right instance or ask an Instance Admin to raise your instance role. See [Instance Connections](instance-connections) and the [Instance Selector](ui-instance-selector) for how instances are picked and remembered. --- # Entity Instructions Entity instructions let you provide custom guidance to the AI about how specific entities or attributes are used in your ERP.net instance. When an entity or attribute is used in an unusual or company-specific way, adding an instruction ensures the AI handles your data correctly. ## Why Use Entity Instructions? ERP.net entities have standard definitions, but every business is different. You might: - Use a standard field for a non-standard purpose (e.g., storing internal codes in a "Notes" field) - Have specific naming conventions or categorization rules - Need the AI to follow domain-specific logic when reading or writing data Entity instructions are merged with the system-wide entity knowledge and delivered to the AI during conversations, so it always has the right context for your instance. ## Managing Entity Instructions Entity instructions are managed per ERP.net instance. Only **Power Users** and **Instance Admins** can add, edit, or delete them. ### Accessing the Page Navigate to **Entity Instructions** from the **ERP instance** submenu in the user menu. This option is visible when: - You are connected to an ERP.net instance - Your instance role is Power User or higher ### Adding an Instruction Click **Add Instruction** and fill in: | Field | Description | |-------|-------------| | **Repository Name** | The entity this instruction applies to (e.g., `General_Products_Products`). Use the search to find the right entity. | | **Instructions** | The main guidance for the AI — describe how this entity or its attributes are used in your company. | | **Common Mistakes** | *(Optional)* List frequent errors the AI should avoid when working with this entity. | | **Examples** | *(Optional)* Provide concrete examples of correct usage to help the AI understand the expected behavior. | ### Editing and Deleting Use the action buttons on each instruction row to edit or delete existing instructions. Changes take effect immediately for all users on the same instance. ## How It Works When the AI retrieves entity metadata during a conversation, it automatically loads any instance-specific instructions alongside the standard entity schema. This means your custom guidance is always available without any extra steps from the user. ## Related - [How Operator Understands ERP.net](/help/erpnet-model) --- # Connected services (MCP servers) A connected service gives Operator's AI extra tools — Slack, Notion, Business Central, a system your team built, anything that speaks the Model Context Protocol. Once a service is switched on, its tools are available to the AI during your conversations. Operator stores each service exactly as other MCP clients write it down, so a configuration you already have can be pasted in unchanged. ## Three kinds of service | Kind | Who can see it | Who adds it | |------|----------------|-------------| | **My servers** | Only you | Anyone, from the Capabilities page | | **Organizational** | Everyone connected to that ERP.net instance | Power Users and Instance Admins | | **Agent's own** | Whoever uses that agent | The agent's owner, in the agent editor | Personal servers need no instance and no special role. Add one, switch it on, and the AI can use it in any of your conversations. ## Adding a service Open **Capabilities → My servers → Add my own server**. Two tabs describe the same thing: - **Settings** — name, address, headers, sign-in and which tools the AI may use. - **Configuration** — the raw JSON. Paste one in and the settings fill themselves; change a setting and the JSON follows. A fixed-credential service looks like this: ```json { "mcpServers": { "businesscentral": { "type": "http", "url": "https://mcp.businesscentral.dynamics.com", "headers": { "TenantId": "${SECRET:BC_TENANT_ID}", "EnvironmentName": "Production", "Company": "CRONUS USA, Inc." } } } } ``` A service where each person signs in with their own account looks like this: ```json { "mcpServers": { "slack": { "type": "http", "url": "https://mcp.slack.com/mcp", "oauth": { "clientId": "YOUR_SLACK_APP_CLIENT_ID", "scope": "channels:read chat:write" } } } } ``` Only services reachable over `https` are supported. A configuration that starts a program on your own machine cannot be used, and Operator says so instead of quietly ignoring it. ### Placeholders in headers Header values may contain placeholders, filled in only at the moment the service is called: - `${SECRET:MY_TOKEN}` — a value kept in Operator's secret store, never shown back to anyone. - `${ERPNET_INSTANCE_TOKEN}` — the signed-in person's own ERP.net token, so the service acts as them. If a placeholder has no value, that header is left out rather than sent half-empty. ### Options Operator adds Everything Operator needs beyond the standard lives under one `x-operator` key, so the rest of the entry stays a plain, portable configuration: ```json "x-operator": { "displayName": "Slack", "label": "slack", "description": "Channels and messages", "allowedTools": ["list_channels", "post_message"], "requireApproval": "always" } ``` `callbackPort`, which some desktop clients use, is accepted so a pasted configuration still works — Operator returns from sign-in through its own page instead. ## Signing in Services with a sign-in section authorize each person separately. - Press **Sign in** on the service and approve it in the window that opens. Operator remembers the result and refreshes it silently while it stays valid. - If an agent needs a service you have not signed in to, it says so in its answer and offers a **Connect** button right there. Approve it, then ask again. - When a sign-in expires, the same button comes back. **Disconnect** forgets it entirely. Some services hand out their own client id automatically; for those you can leave the client id empty. ## Testing a service **Test connection** performs a real handshake and lists the tools the service offers. Those tools then appear as checkboxes, so you can allow all of them or only the ones you want. Until a test has run, all tools are allowed. If a connected MCP server fails while a conversation is starting, Operator names it in the error message when possible. Open **Capabilities**, test or disable that server, then try your message again. ## Approval By default the AI asks before each use of a connected service, the same way it asks before changing data. Turn **Ask before each use** off only for services you fully trust. ## Examples - "Post the weekly sales summary to the #sales channel." — uses your Slack service, after you have signed in. - "Pull the open purchase orders from Business Central and compare them with ERP.net." — uses an organizational service with fixed credentials. - "What can you do with my connected services?" — the agent lists the tools it currently has. --- # Permission Policies *Restrict what data assigned users can read and modify through Operator* Permission Policies let instance admins define exactly which parts of the ERP.net data model an Operator user is allowed to access — on top of ERP.net's own security. They are managed per ERP.net instance from **Manage Instance Users → Policies**. ## Why Use Permission Policies? ERP.net's built-in roles control access at the database level, but they apply uniformly to everyone using a given login. Operator policies let you: - Give a sales rep AI access only to **CRM** entities, even though their ERP.net login can technically read more. - Restrict a client user to a single namespace such as `Logistics.Sales`. - Allow a controller to **read** finance data but block any **update** through the AI. - Force certain users to stay on-topic (no general chit-chat with the AI — see [Allow off-topic conversations](#allow-off-topic-conversations) below). Policies are enforced **on top of** ERP.net's own security. ERP.net checks always run; the policy simply adds a second filter that blocks access to anything outside the granted scopes. ## Who Can Manage Policies? Only **Instance Admins** (instance role 40) can create, edit, delete, and assign Permission Policies. Other users see the assigned policy on their own account in read-only form. ## Accessing the Policies Page 1. Open the user menu and choose **Manage Instance Users**. 2. Switch to the **Policies** tab. You will see the list of policies defined for the current ERP.net instance, plus how many users each policy is assigned to. ## Creating or Editing a Policy Click **New Policy** (or the pencil icon on an existing policy). Each policy has: | Field | Description | |-------|-------------| | **Name** | Short label shown when assigning the policy to users (e.g. *Sales Reps*, *Read-only Finance*). | | **Description** | Optional notes for other admins explaining the intent. | | **Allow off-topic conversations** | Master switch that controls Topic Guard for assigned users — see below. | | **Scope tree** | Visual tree of all ERP.net namespaces and entities the policy grants access to. | ### Working with the Scope Tree The scope tree is the heart of a policy. It mirrors the ERP.net data model — namespaces (e.g. `Crm`, `Logistics`, `Finance`) at the top, with sub-namespaces and individual entities underneath. - **Tick a checkbox** to grant access to that node and everything beneath it. Ticking `Crm` grants the entire CRM namespace. - **Expand a branch** with the chevron to pick individual children instead. - **Indeterminate state** (◪) means *some* descendants are granted but not all — useful for spotting partial coverage at a glance. - **Read / Update toggle** appears next to each granted node. **Update** automatically includes create, update and delete; **Read** is query-only. - **Search box** filters the tree in real time and auto-expands matching branches so you can find an entity quickly. When you save, Operator collapses your selection to the smallest equivalent set of scope entries. For example, if you tick every entity inside `Crm`, the saved policy stores a single `Crm.*` entry instead of dozens of individual ones. Re-opening the policy expands them back into the tree. ### Allow off-topic conversations The **Allow off-topic conversations** switch controls whether assigned users can chat with the AI about non-work themes (the weather, general knowledge questions, casual conversation, etc.). - **On (default)** — users can freely choose whether to enable Topic Guard in their own **Settings → AI-enhanced**. - **Off** — Topic Guard is **forced on and locked** for every user assigned to this policy. Their Settings dialog shows the toggle as disabled with a hint that the instance admin controls it. The AI will politely refuse anything unrelated to ERP.net or the user's work. This is the right setting for client-facing or shared-account scenarios where you want to keep AI usage strictly on-topic. ## Assigning a Policy to a User 1. Go to the **Users** tab in **Manage Instance Users**. 2. Locate the user and use the **Policy** dropdown in their row. 3. Pick a policy or choose **No policy** to remove the restriction. A user without a policy keeps unrestricted Operator-side access — ERP.net's own security still applies. Policy assignment changes are recorded in the instance **Audit Log**, so you can always trace who changed what and when. ## How Enforcement Works Whenever an assigned user runs a tool that reads or writes ERP.net data, Operator: 1. Determines the entity being accessed (e.g. `Crm.Customers`). 2. Looks up the user's policy and checks whether the entity is covered. 3. For writes, also confirms the policy grants **Update** on that scope. 4. Blocks the call with a clear message if the entity is outside the allowed scopes. Read-only policies still let users **see** business data the AI returns — they just can't trigger create/update/delete operations through the AI. To restrict reads, simply leave the relevant branches unticked. The AI is also informed about restrictions **at discovery time** — when it looks up an entity (for example to plan a query), the response already tells it whether the user has full, read-only, or no access. This way the AI can warn the user proactively instead of attempting a call that will be denied, and it knows not to keep retrying similar lookups. ## Tips - Start with broad namespace ticks (e.g. all of `Crm`) and only narrow down where it matters. Saved policies are easier to audit when they use namespace-level entries. - Use the description field to record *why* a policy exists — future admins will thank you. - Combine **Allow off-topic conversations = Off** with a tightly-scoped policy to create a strict, business-only AI experience for client users. - If a user reports being blocked from data they expect to access, check both their ERP.net role **and** their assigned policy. ## Related - [ERP.net Integration: Security, Identity, and Permissions](/help/erpnet-security) --- # Operator in the ERP.net Web Client *Show Operator as a side panel next to any record.* Once registered, Operator appears on the right-hand side of every single-record form in the ERP.net Web Client. Open **Sales Order 12345** or the customer **ACME** and the assistant is already there, already knowing which record is on the screen. ## What users get - A panel on every record form — sales orders, customers, products, and everything else. - The open record is handed to the assistant automatically, so a user can type "summarise this", "who bought it last month" or "what changed recently" without naming the record. - Conversations start with the **Business Specialist**. - Opening a different record reloads the panel with the new record in context. **Example** > A salesperson opens Sales Order 12345, types "is anything on this order out of stock?" in the panel, and gets the answer for that exact order. ## Registering the panel Registration is done once per ERP.net instance by an **Instance Admin**: 1. Open the **instance selector** in the top bar and go to **Manage instance**. 2. Choose **Web Client Integration**. 3. Read what the panel does, then press **Register side panel** and confirm. 4. Reload the ERP.net Web Client and open any record. The page shows whether the panel is currently registered, lets you re-apply the registration after an update, and lets you **Remove** it again. **View payload** shows exactly what is written to the instance, for admins who want to inspect it. ## Notes - Only Instance Admins see this page, and the registration applies to everyone working in that instance's Web Client. - Each user still signs in to Operator inside the panel with their own account, and sees only the data their ERP.net rights allow. - Removing the registration takes effect after the Web Client is reloaded. --- # Buying AI Credits Operator lets you top up an ERP.net instance with **AI credits** that fund AI requests run against that instance. ## Who can buy Only users with the **Instance Admin** role on a connected instance can purchase credits for that instance. Open the instance dropdown in the top bar and pick **Buy AI Credits** — the menu entry only appears when the active instance is one you administer. You can also reach the page directly at `/billing-credits`. ## How it works - Credits are attached to the **instance** (identified by its base URL), not to your personal user account. Anyone connected to that instance shares the same pool. - Purchases are **one-time top-ups** — there are no subscriptions, no auto-renewal. - Payments are processed by Stripe. Operator never sees your card details. ## Packages Prices below are **net**, excluding tax. Any applicable VAT or sales tax is added at checkout based on your country. | Credits | Price | Per credit | |--------:|------:|-----------:| | 100 | €35 | €0.35 | | 1,000 | €300 | €0.30 | | 10,000 | €2,500 | €0.25 | | 100,000 | €22,000 | €0.22 | ## Invoices and tax Stripe handles the payment end to end for credit purchases: - Tax is calculated and added at checkout for your country. - The **invoice / receipt is issued and emailed by Stripe** right after payment — you do not need to request it from Operator. - The same invoice is also always available inside Operator: after a purchase completes, a **View invoice** link appears, and every paid purchase in **Credit management → Purchase history** carries a link to its invoice (with the invoice number). Use it if the email is lost or went to a different mailbox. - Your card statement shows `LINK.COM*` followed by the Operator descriptor. ### Buying as a company (VAT number, reverse charge) Business buyers can enter their company details and **VAT number during checkout** — the payment step is hosted by Stripe and collects the billing address and business identity itself. - Where the **reverse charge** applies (for example, a VAT-registered business in another EU country), no VAT is added and the invoice is issued accordingly. - Where it does not apply, VAT for your country is added on top of the net price. - Either way the invoice is issued by Stripe as the seller of record, so no separate request to Operator is needed. ## After payment Once Stripe confirms the payment, the instance balance updates automatically — usually within a few seconds. The Buy AI Credits page polls in the background after a successful checkout, so you'll see the new balance without refreshing. Every top-up is recorded under **Purchase history** on the same page, with date, package size, amount and status. Amounts shown there are the net package prices, excluding tax. ## Test mode In the preview environment, the page runs in Stripe **test mode**. Use Stripe's test card `4242 4242 4242 4242` with any future expiry and any 3-digit CVC. ## Choosing which budget pays for a connection To bill a specific connection's AI usage to a per-instance budget instead of the home pool, see [AI Credit Budget per Connection](instance-connections#ai-credit-budget-per-connection). --- # Managing User AI Credit Budgets Once an instance pool has been topped up (see [Buying AI Credits](billing-credits)), instance admins can hand out personal AI credit budgets to individual users. This is what powers the **per-connection budget source** — a user with their own per-instance budget can switch a connection to bill that budget instead of their home pool. This page covers the **User Budgets** tab on `/billing-credits` (Manage → AI Credits → *User Budgets*). ## Who can use this - You must be an **Instance Admin** of the currently selected instance. - The User Budgets tab only operates on the instance shown in the header. To manage another instance, switch it on the home screen and re-open Manage → AI Credits. ## What the table shows Every user that has a connection to this instance appears as a row, with: - **User** — display name and email. A small home icon marks the user's home instance. - **Balance** — the user's current personal AI credit balance (shared across all instances they use). - **This month** — credits topped up to this user from *this instance's* pool in the current calendar month. - **Monthly auto limit** — the cap on how many credits *automatic* top-ups may add to this user per month. Empty means no cap. Manual top-ups are never blocked by it and do not consume it — as an administrator you can always top up any amount the instance pool covers. - **Auto top-up** — `Off`, or `threshold → ceiling` when enabled. Use the search box to filter by name or email. ## Top up a user manually Open the row's `⋯` menu and pick **Top up now…**. - **Source instance** — the instance pool you are funding the top-up from (the active one). - **Credits to add** — how many credits to move from the pool into the user's personal balance. - **Note** — optional, free-text reason. Visible later in the top-up history. The dialog blocks the action when: - The pool has fewer credits than you're trying to send. - The amount would exceed this user's monthly limit on this instance. On success, the user's balance updates immediately and an entry is written to their top-up history. ## Set a monthly limit Open the row's `⋯` menu and pick **Edit settings…**, then fill in **Monthly auto top-up limit (credits)**. - The limit is enforced per calendar month, per (user, instance) pair. - Manual top-ups *and* auto top-ups both count against this limit. - Leave the field empty to remove the cap entirely. The dialog shows how much you've already used this month so you can size the cap sensibly. ## Set a daily usage limit Open **Edit settings…** and fill in **Daily usage limit (credits)** to cap how much a user can spend on this instance in a single day. - Whole credits only. Leave the field empty to remove the cap entirely. - It caps the **sum of AI-credit usage** by that user on this instance within one UTC day, and it is **independent of the user's remaining balance** — a user with credits to spare can still hit the daily cap. - It is checked at the **start of each new conversation turn**. A long-running task that has already started (including background automations mid-flight) is allowed to finish so partial work is never lost. - When a user hits the cap: - The next message they send in any conversation on this instance ends immediately with a chat reply explaining the situation. - They also receive a **notification**, so background runs and unattended sessions surface the reason. - The cap resets at **00:00 UTC**. Example: setting a daily limit of `200` for a user means the operator refuses to start new turns once their same-day usage on this instance reaches 200 credits, even if they still have thousands in their personal balance. ## Configure auto top-up In the same **Edit settings…** dialog, switch **Auto top-up** on and set: - **Threshold** — when the user's balance drops below this number of credits, an auto top-up fires. - **Ceiling** — auto top-up tops the user *up to* this number. (It does not add a fixed amount — it brings the balance to the ceiling.) Rules: - Ceiling must be greater than threshold. - Auto top-ups are funded from this instance's pool, so the pool needs enough credits at the time of the run. - Auto top-ups respect the monthly limit. If a top-up would breach the cap, it is skipped. - Auto top-ups run on a **10-minute cycle**. They are not instant, so set the threshold high enough that a user will not run out before the next cycle picks them up. ### Planning the threshold Because auto top-ups are evaluated only every 10 minutes, the threshold is the safety margin, not the point at which you want the user to actually stop. Size it so the user cannot burn through the gap between threshold and zero in the time it takes for the next cycle to run, plus the time a long turn may already be in flight. A good rule of thumb: - A single chat turn can easily cost 5–20 credits. - A saved-agent run or multi-step task can cost 30–100 credits. - App Builder sessions with many iterations can cost several hundred credits in a short window. Pick a threshold that leaves enough headroom for the user's typical workload between cycles. ### Recommended setups | Threshold → Ceiling | Best for | Why | |----|----|----| | **50 → 100** | Chat-only users | Minimum viable setup. Covers light chat use between 10-minute cycles without interrupting work. | | **100 → 200** | Chat users who also run saved agents | Normal safety margin for mixed daily use — chat plus occasional agent runs. | | **200 → 400** | Heavy App Builder users | Larger buffer for users who run long iterations or build apps, where individual turns can be expensive. | These are starting points. Monitor the user's actual burn rate in the top-up history and raise the threshold if they ever hit zero before an auto top-up fires. Auto top-ups appear in the history with the **Auto** badge. ## View top-up history The `⋯` menu also has **View history**, which lists the most recent 100 top-ups for that user — across all instances you have visibility into: - **Date**, **Type** (Manual / Auto / Adjustment), **Source** instance, **Credits**, **Balance after**, **Note**. Use it to audit who funded what and to investigate billing questions from your users. ## How this ties into per-connection billing A user's personal balance is the budget that the **This instance** option in *My Connections → Edit Instance → AI credit budget* draws from. The option only becomes selectable on a given instance once you, as that instance's admin, have topped the user up there. See [AI Credit Budget per Connection](instance-connections#ai-credit-budget-per-connection) for the user-side view. --- # Budget profiles Every instance has default **budget profiles** that seed the settings for new user budgets. Instance admins can adjust these once, and every new user gets those defaults automatically. ## What a profile controls - **Initial credits** — how many credits a new user starts with when their budget is first created. - **Daily usage limit** — how many credits a user may burn per day (resets 00:00 UTC). - **Monthly auto top-up cap** — how many credits per calendar month a user may receive as *automatic* top-ups from the instance pool. Manual top-ups are unaffected. - **Auto top-up** — optional: when balance drops below **threshold**, top up back to **ceiling** from the instance pool. ## Profile kinds Each instance has two per-instance profiles, seeded after the first credit purchase: - **Internal** — applied to internal users of the instance. - **Client** — applied to client-mode users of the instance. There is also a single, global **Advisor** profile (system-managed) that caps free Advisor usage at 50 credits per user per day. ## Editing profiles Go to **Billing → Instance budgets**, pick the instance you administer, and use **Default budget profiles**. Changes apply to **newly created** user budgets. Existing user budgets keep the settings they were created with — adjust them per user under **User budgets**. ## Examples - Give every new internal user 100 free credits to try things out: set **Initial credits = 100**. - Cap heavy users at 200 credits/day on this instance: set **Daily usage limit = 200**. - Never let anyone auto-consume more than 1000 credits/month from the pool: set **Monthly auto top-up cap = 1000**. - Keep typical chat and saved-agent users topped up: enable **Auto top-up** with **threshold 100 / ceiling 200**. For heavier App Builder users, use **threshold 200 / ceiling 400**. See [Managing User AI Credit Budgets](billing-user-budgets#configure-auto-top-up) for the full recommended setups and the 10-minute cycle behavior. --- # Credits for consultants If you consult for one or more customers, Operator lets you choose **whose credits pay** for each connection you use. ## The two credit sources Each internal-user connection has a **credit source**: - **Home** — usage is billed to your own home instance. Use this when *you* pay for the AI usage even though you are working inside a customer's data. - **This instance (local)** — usage is billed to the connected instance. Use this when the *customer* pays for your AI usage on their instance. Client-mode connections are always billed **locally** (to the client's instance). ## Setting a home instance The first internal connection you add becomes your **home**. You can change it later from the instance selector. Your home is the instance whose pool funds "home" billing across all your other connections. ## Choosing per connection In the instance selector, click **Edit** on any non-home internal connection and pick a **credit source**: - Pick **Home** to charge your own instance. - Pick **This instance** to charge the customer's instance. This option is only available when the customer's instance has credits allocated to you (ask their admin to top you up). ## Typical scenarios - **Consultant working on client site, client pays**: add an internal connection to the client's instance, ask the client's admin to top up your per-instance budget, and set **credit source = This instance**. - **Consultant working on client site, you pay**: keep **credit source = Home**. Usage is drawn from your own instance's pool. - **Client-mode connection**: no choice — always billed to the client's instance from your client-mode user budget on that instance. ## Free Advisor Advisor works without any connection and is **free** up to a per-user daily cap. It never draws from your paid budgets. ## Before paid usage starts Until AI credits become billable, Operator only tracks usage — it does not deduct credits or block work. Once billing goes live, the connection's **credit source** decides which pool is charged. --- # Billing FAQ Quick answers to common questions about buying and loading AI credits. ## Why can't I buy credits for my ERP.net instance? The **Buy AI Credits** option is missing or the purchase fails — most often because **Operator is not installed on that instance**. Operator's credits live on the instance, so the instance needs Operator installed before you can load credits into it. This works even when you are connected to the instance with your user — the connection alone is not enough. ### How to fix it 1. Install Operator on the instance from the ERP.net Marketplace: [Operator in the ERP.net Marketplace](https://marketplace.erp.net/apps/operator). 2. Once installed, open the instance dropdown in the top bar and pick **Buy AI Credits** (available to instance admins), or go directly to `/billing-credits`. For the full purchase flow, see [Buying AI Credits](billing-credits). --- # URL Parameters *Deep linking, embedding, and pre-configuring the user experience* The chat interface supports URL parameters for deep linking, embedding, and pre-configuring the user experience. ## Layout & Display | Parameter | Values | Description | |-----------|--------|-------------| | `layout` | `full` (default), `embedded` | Controls the display mode. `embedded` hides the header for seamless iframe integration. | | `theme` | `dark`, `light` | Sets the color scheme. Persists for future visits. | **Examples:** ``` /?layout=embedded /?theme=light /?layout=embedded&theme=dark ``` --- ## Input & Autorun | Parameter | Values | Description | |-----------|--------|-------------| | `input` | Any text (URL-encoded) | Pre-fills the chat input field with the specified text. | | `autorun` | `true`, `1` | When combined with `input`, automatically sends the message on page load. | **Examples:** ``` /?input=Show%20my%20orders /?input=List%20invoices&autorun=true /?layout=embedded&input=Help%20me&autorun=1 ``` --- ## App Full-Screen | Parameter | Values | Description | |-----------|--------|-------------| | `app` | App slug | Renders the specified app in full-screen mode — no chat, no header, no sidebar. | The `app` parameter accepts the app's slug (e.g., `my-inventory-app`). When set, the entire UI is replaced with the app's preview filling the viewport. This can be combined with `instance`, `enterprise`, and other parameters for full ERP context. **Examples:** ``` /?app=my-inventory-app /?app=my-inventory-app&instance=demo&enterprise=ACME /?app=my-inventory-app&layout=embedded ``` ### Error Handling | Scenario | Behavior | |----------|----------| | Slug not found | Error toast displayed, falls back to normal chat view | | User not authenticated | Landing page shown, parameters preserved for after login | | No files / no index.html | "No Preview Available" message shown full-screen | --- ## Instance Selection | Parameter | Values | Description | |-----------|--------|-------------| | `instance` | UIN or Base URL | Selects the specified ERP.net instance connection. | The parameter accepts: - **UIN** (subdomain): e.g., `mycompany` - **Full Base URL**: e.g., `https://mycompany.my.erp.net` - **Hostname without protocol**: e.g., `mycompany.my.erp.net` If the instance is found in the user's connections, it becomes the active connection. If not found, an error toast is displayed. **Examples:** ``` /?instance=mycompany /?instance=https://mycompany.my.erp.net /?instance=demo.my.erp.net ``` --- ## Enterprise Context | Parameter | Values | Description | |-----------|--------|-------------| | `enterprise` | GUID or Name | Sets the enterprise company context. | | `enterpriseLocation` | GUID or Name | Sets the location within the enterprise company. | ### Matching Logic - **GUID**: Exact match (case-insensitive) - **Name**: Contains match (case-insensitive) The enterprise context is applied after the instance connection is established. If a match is found, the context is set and the UI updates accordingly. **Examples:** ``` /?enterprise=My%20Company%20Ltd /?enterprise=8F42B1C3-5D9E-4A7B-B2E1-9C3F4D5A6E7B /?enterprise=ACME&enterpriseLocation=Warehouse%201 /?instance=demo&enterprise=Partner%20Corp ``` --- ## Entity Context | Parameter | Values | Description | |-----------|--------|-------------| | `entityType` | Repository name | The ERP.net entity type, e.g. `General.Products.Products`. | | `entityId` | GUID | The id of the specific record. | Both parameters must be supplied together. Operator loads the record from the connected instance and tells the agent its type, its id and its readable name, so the user can say "summarise this" or "who bought it last month" without naming the record. The record stays part of the context for the whole session. **Examples:** ``` /?entityType=General.Products.Products&entityId=8F42B1C3-5D9E-4A7B-B2E1-9C3F4D5A6E7B /?instance=demo&entityType=Crm.Sales.SalesOrders&entityId=8F42B1C3-5D9E-4A7B-B2E1-9C3F4D5A6E7B /?instance=demo&entityType=Crm.Sales.SalesOrders&entityId=8F42B1C3-...&input=Summarise%20this&autorun=1 ``` If the record cannot be read (wrong id, unknown entity type, or no read rights), a warning is shown and the agent still receives the entity type and id — only the readable name is missing. --- ## Agent Preselection | Parameter | Values | Description | |-----------|--------|-------------| | `agent` | System agent key, user-agent identifier, or user-agent UUID | Preselects the active agent when the chat loads. | ### Resolution order (case-insensitive, first match wins) 1. **System agent key** — e.g. `erp_advisor`, `business_specialist`, `sales_executive`, `erp_manager`, `partner`, `app_builder`, `agent_builder`. 2. **User-agent identifier** — the short identifier defined on the user agent. 3. **User-agent UUID** — the agent's `id`. Names are not matched. ### Availability The agent must be available to the signed-in user: - **System agent** — must satisfy the user's account level and be supported in the current connection mode (unconnected / internal / client). - **User agent** — must be owned by the user or shared with them. If the value doesn't match anything the user can access, an error toast is shown and the selection falls back to the mode-aware default: **Business Specialist** in internal mode, **Sales Executive** in client mode, and **ERP Advisor** when no instance is connected. The same fallback applies when no `agent` parameter is provided. Ignored when `app=` is set (full-screen app owns the UI) or when opening a specific conversation URL (`/c/:id`) — the conversation's own agent stays authoritative. **Examples:** ``` /?agent=business_specialist /?agent=app_builder /?agent=sales_executive&instance=demo /?agent=my-importer /?agent=8f42b1c3-5d9e-4a7b-b2e1-9c3f4d5a6e7b /?agent=my-importer&input=Import%20today%27s%20file&autorun=1 ``` --- ## Update Mode | Parameter | Values | Description | |-----------|--------|-------------| | `updateMode` | `read-only` (default), `read-write` | Controls whether the chat starts in read-only or read-write mode. When omitted, the chat starts **read-only** so tools that modify data are disabled until the user explicitly enables them. | Applied on page load. Ignored when opening an existing conversation URL (`/c/:id`) — the conversation's own stored mode stays authoritative. **Examples:** ``` /?updateMode=read-write /?agent=business_specialist&updateMode=read-write ``` --- ## Combined Examples ### Embedded Chat with Pre-filled Input ``` /?layout=embedded&input=What%20are%20my%20pending%20orders%3F ``` ### Full Setup with Autorun ``` /?instance=demo&enterprise=ACME&enterpriseLocation=Main%20Office&input=Show%20dashboard&autorun=true ``` --- ## Execution Order Parameters are processed in the following order: 1. **Parse all parameters** on component mount 2. **Instance selection** executes first (waits for connections to load) 3. **Enterprise context** selection executes after instance is active (waits for tokens) 4. **Entity context** is loaded after the instance settles (waits for tokens) 5. **Agent preselection** executes after instance settles and user agents load 6. **App full-screen** resolves slug to app and enters full-screen mode (waits for user apps to load) 7. **Input prefill/autorun** executes after context is set Each step is protected by refs to ensure it only runs once per page load. --- ## Error Handling | Scenario | Behavior | |----------|----------| | Instance not found | Error toast displayed, no instance change | | Enterprise company not found | Error toast displayed, context not set | | Location not found | Error toast displayed, context not set (even if company matched) | | Agent not found or not available for the user | Error toast displayed, selection falls back to the mode-aware default (Business Specialist in internal mode, Sales Executive in client mode, ERP Advisor when unconnected) | | Only one of `entityType` / `entityId` given | Warning toast displayed, no entity context set | | Entity cannot be read or does not exist | Warning toast displayed, agent still receives entity type and id (no readable name) | | App slug not found | Error toast displayed, falls back to normal chat view | | User not authenticated | Parameters are ignored until user signs in | | No active connection | Enterprise context waits until instance is connected | --- # Release Notes *Latest updates and improvements to Operator* Release notes are organized by month. Pick a month to see the updates that shipped in that period. ## Available updates - [September 2026](/help/release-notes-2026-09) — Add personal MCP servers for tools only you use; organizational MCP servers are available again for whole teams; Pro apps can connect securely through procedures; explore working apps and agents in the Examples Gallery; automate apps with triggers; queue messages; and get dashboards and diagrams in answers. - [August 2026](/help/release-notes-2026-08) — Digital Entities: always-ON agents that remember, watch, and act on their own; plus Pro app table storage, safe external service calls, more file room, retirable records, automatic change history, and a business date per table. - [July 2026](/help/release-notes-2026-07) — Apps can open and host each other; App Builder now uses 2×–5× fewer credits; installable app PWAs; new Manage Instance hub and Spend Statistics; persistent app event logs with structured, queryable log streams. - [June 2026](/help/release-notes-2026-06) — Agent Optimization (per-instance pre-computed knowledge), fresh-context-by-default runs, App Builder multi-conversation & per-instance threads, longer 15-minute builds. - [May 2026](/help/release-notes-2026-05) — Agent Delegation capability (sub-agents) and follow-up polish; Active instance now persists per tab and across sessions; Conversation Properties dialog. - [April 2026](/help/release-notes-2026-04) — Per-connection AI credit budget, User Budgets, Home Connection, and more. - [March 2026](/help/release-notes-2026-03) — Permission Policies, Instance Management improvements, indexing upgrades. - [February 2026](/help/release-notes-2026-02) — Apps platform expansions, sharing, deployments, automations. - [January 2026](/help/release-notes-2026-01) — Foundational updates and early-year releases. --- # September 2026 ### Bring your own connected services to any agent *September 28, 2026* — **You can now add personal MCP servers for tools only you use, and organizational MCP servers are available again for whole teams** MCP servers connect Operator's agents to services such as Slack, Notion, Business Central, and tools built by your company. Organizational MCP servers were temporarily unavailable while their security model was strengthened; they now work again. - **Your own servers** — anyone can add a personal MCP server from **Capabilities → My servers**, without needing an ERP.net instance or a special role. It stays private to you and can be used in any of your conversations. - **Shared across an organization** — Power Users and Instance Admins can add an organizational MCP server once and make its tools available to everyone connected to that ERP.net instance. - **Sign in as yourself** — when a service supports personal sign-in, each user connects their own account. The agent can offer a **Connect** button directly in the conversation when access is needed. - **Choose exactly what the AI may use** — test the connection to see the server's tools, allow only the ones you want, and decide whether Operator should ask before each use. - **Clearer problems** — if a connected MCP server fails, Operator names it when possible and points you to **Capabilities** to test or disable it. For example, connect your personal Slack account to ask an agent to post a weekly summary, or add an organizational Business Central server so your team can compare its open purchase orders with ERP.net. See [**Connected services (MCP servers)**](/help/mcp-servers). ### Apps can now connect securely on your behalf *September 27, 2026* — **A Pro app can now log in to other services and call them safely — the part that must never happen in your browser** Many things an app might want to do are not safe to do from the browser: signing in to a service that needs a non-standard login flow, calling an API with a private key, talking to a system that only accepts connections from a server. A Pro app can now run **procedures** — small jobs the App Builder writes for it, which run on Operator's servers instead of in your browser. - **Just describe what the app should be able to do** — *"Add a button that fetches today's currency rates from our provider's API."* The App Builder writes the procedure; you press the button. - **Credentials stay on the server** — keys and secrets used by a procedure never reach your browser, so nothing sensitive is exposed by simply opening the app. - **Handles tricky logins for you** — services that need custom sign-in flows, signed requests, or server-only endpoints are no longer off-limits for an app. - **Runs to completion, even if you leave** — the job runs on the server; closing the app while it works changes nothing. - **Every run is on record** — each procedure keeps its own history in the app's Cloud tab, so you can see when it ran, whether it succeeded, and what it reported. **How this differs from Web Requests.** Web Requests already let an app make a single call to another service with a standard sign-in — a stored key or a regular company login — and they are included in the daily Cloud cost. Procedures go further: they can run any secure logic the browser must not, such as custom logins, signed or chained calls, and keeping a session open. Because of that, each procedure run costs a little (0.1 credit, once billing starts after BETA). Start with a Web Request; the App Builder switches to a procedure only when one call is not enough. Procedures need a **Pro app** and are set up by the App Builder in Design mode — just say what the app should be able to do. See [**Procedures**](/help/pro-apps-procedures) under *Apps*. ### Explore the new Examples Gallery *September 26, 2026* — **A gallery of working example apps and agents shows what you can build with Operator — and every example opens live** Wondering what an AI-built app looks like? The Examples Gallery is a collection of ready-made apps — an online shop, a door configurator, a service dispatch board, a machine configurator, a purchase invoice workflow, an email campaign studio, and more — each one openable in a single click. - **See it before you build it** — every example is a real, working app you can click through, not a description of one. - **More than apps** — the gallery also shows example agents, so you can see how both sides of Operator work in practice. - **Open in one click** — each card links straight to the live demo, on the gallery's [public address](https://operator.net/examples) or from inside Operator. - **Demo data, real potential** — the demos run on sample data and are not connected to a real ERP instance. With Operator, the same apps connect directly to your ERP.net data — or, with a small setup, to any other ERP. Inside Operator, the gallery is always at hand: open your profile menu, hover **Build**, and choose **View Examples Gallery**. Or visit it without signing in at [operator.net/examples](https://operator.net/examples). ### Apps can now work on their own with triggers *September 23, 2026* — **An app no longer waits for somebody to open it — a trigger lets it act on a schedule or when something happens** A trigger is a small script the App Builder writes and keeps with your app. It runs on the server exactly as written — every morning at eight, when an email arrives, when a webhook is called — and costs no AI credits. Just say in plain words what should happen and when. - **Runs while nobody is watching** — *"Every weekday at 07:30, refresh the open-orders table from ERP.net"* and the app shows fresh data the next time you open it. - **Reacts to events** — incoming emails, webhook calls, and record changes can all wake up your app, using the same events that already drive agents and automations. - **PDF reports by email** — *"Every Monday, email last week's sales by customer as a PDF to the sales team."* A copy of each report is kept in the app's files. - **Tied to your data** — a trigger can be bound to a specific ERP.net instance, so it reads and writes exactly that instance's data even when nobody is connected. - **Easy to adjust** — *"Move the daily snapshot to 07:30"* changes only the time; the script and everything else stay untouched. - **Watch them run** — the **Triggers** tab in the App Builder shows each trigger's next run, its history, and anything that went wrong. Triggers need a **Pro app** and are set up by the App Builder in Design mode — just describe what should happen. See [**React to schedules and events**](/help/pro-apps-triggers) under *Apps*. ### Agents can now draw diagrams in their answers *September 22, 2026* — **When an answer describes a process or a flow, agents can now show it as a diagram right in the conversation** Besides charts and dashboards, agents can now include diagrams — process steps, workflows, relationships, or timelines drawn as connected boxes and arrows. A path that took a paragraph to describe becomes something you can follow at a glance. - **Diagrams when they help** — the agent adds one when the answer naturally describes a process, flow, states, or dependencies; simple answers stay text-only. - **Interactive** — zoom and drag to explore, open full screen, or download as an image. - **Controls never get in the way** — zoom and download options sit in their own slim row above the diagram and appear only when you hover, so nothing is covered. - **Readable at first glance** — diagrams are drawn to fit the conversation area, so long processes flow top-to-bottom instead of shrinking into tiny text. - **Plays well with dashboards** — one answer can contain both a diagram for the structure and a dashboard for the numbers. For example, ask *"How does a sales order move from creation to invoicing?"* and the answer can show the whole path as a diagram, with the explanation below it. See [**Visuals in answers**](/help/dashboards-in-answers) under *Chat*. ### Queue your next message while the agent is working *September 15, 2026* — **You no longer have to wait for an answer to finish before sending the next one — just add it to the queue** When an agent is still working and you already know what you want to ask next, you can queue your message instead of stopping the current answer. It runs automatically the moment the agent finishes — in any conversation, including the App Builder and the Agent Builder. - **One press to queue** — while an answer is running, sending a message (or the clock button next to **Stop**) adds it to the queue instead of interrupting. - **Queued messages survive closing the tab** — they are kept safely, so whatever you queued still runs when you come back. - **Edit or remove before they run** — queued messages appear as small cards above the message box; change the text or drop them entirely while there is still time. - **Stop holds the queue** — stopping the agent also pauses everything queued; **Resume** (or simply sending a new message) continues it. For example, in the App Builder you can queue *"Now make the header dark"* while the first change is still being built — it will run right after. ### Agents can now answer with dashboards *September 14, 2026* — **Business Specialist and the other text agents can now show their answers as charts, KPI cards, and tables, right inside the conversation** When you ask a text agent a numbers question — turnover by month, top customers, stock levels — the answer can now arrive as a visual dashboard instead of only text. You get an at-a-glance summary you can read in seconds, without leaving the chat. - **KPI cards** — headline figures like total revenue or open orders, each with its value and unit. - **Bar, line, and doughnut charts** — trends, comparisons, and breakdowns drawn directly in the answer, with legends and labels. - **Tables** — the underlying rows when you need the exact numbers behind a chart. - **Real data only** — agents build dashboards exclusively from data they have actually retrieved; they never invent figures, and each value names its unit or currency. - **Matches your theme** — dashboards follow your light or dark theme automatically. Just ask for the numbers as usual — for example, *"Show me turnover by month for this year as a chart."* The agent decides when a dashboard adds clarity and includes one in its reply. ### Operator is now integrated inside the ERP.net Web Client *September 14, 2026* — **You can open Operator as a side panel directly from entity forms in the ERP.net Web Client** Instance admins can register Operator as an extension panel inside the ERP.net Web Client. Once registered, a new **Operator** panel appears on entity forms, so users can ask questions about the current record without switching tabs or copying context. - **Context travels automatically** — the panel receives the current entity type and record ID, so agents like Business Specialist already know which record you are looking at. - **Works on any entity form** — register it once and it appears across all entity forms in the instance. - **Managed under Instance settings** — go to **Manage instance → Web Client Integration** to add, update, or remove the panel. - **Requires ERP.net Web Client v.27** — the extension-panel feature is available starting with ERP.net version 27. ### Agents can now send you notifications *September 13, 2026* — **Agents can reach out on their own — to you, and to anyone on the platform who allows it** Agents with the new **Notifications** capability can now send Operator notifications proactively, instead of only replying in a conversation. This is especially useful for always-ON agents like Digital Entities, which can now deliver reminders and alerts even while you are away. - **Notify the owner directly** — an agent can always message the person who created it, for example to report that a nightly import finished or to deliver a scheduled reminder. - **Notify anyone on the platform** — agents can look people up by name or email and send them a notification too, but the first message arrives as a permission request; only after the recipient taps **Allow** do further notifications come through. - **You are in control** — recipients can allow or block notifications from each agent, and every notification shows which agent sent it. - **Sensible limits** — each agent can send up to 20 notifications per recipient per day, so nobody gets flooded. To enable it, turn on the **Notifications** capability for an agent in its settings. ### Operator now sends device notifications *September 12, 2026* — **Operator can now push notifications straight to your phone, tablet, or desktop** You no longer need to keep Operator open in a browser tab to stay on top of important alerts. Once you enable device notifications, new notifications from the platform are delivered to your installed Operator app or browser in real time. - **Install Operator as a PWA** — add it to your home screen or desktop for the best experience and reliable delivery. - **Notifications turn on automatically with install** — once you install Operator as a PWA, device notifications are enabled right away on that device, so you do not have to remember to turn them on later. - **Enable notifications from the user menu** — open your profile menu, choose **Device notifications on this device**, and turn them on. - **Works across devices** — each device you enable is registered separately, so you can receive notifications on your phone, your laptop, or both. - **Notifications drop-down helps you opt in** — if device notifications are not enabled on the current device, a banner at the top of the notifications panel explains how to turn them on. - **Automatic cleanup** — stale or expired device registrations are removed, so you do not receive duplicate or broken deliveries. Device notifications are delivered for any notification you would normally see inside Operator, including broadcasts sent from the admin panel. ### App Builder reasoning levels *September 11, 2026* — **You can now choose how deeply the App Builder thinks when building apps** The App Builder now supports five reasoning levels, so you can trade speed against depth depending on the task. Pick the level from the reasoning badge in the chat header before you send a message: - **Quick** — fastest responses for small edits and straightforward tweaks. - **Smart** — balanced thinking for everyday changes and UI work. - **Expert** — deeper reasoning for multi-file features and app structure; this remains the default. - **Genius** — maximum analysis for complex refactors, performance work, or tricky bugs. - **Savant** — the deepest thinking available, reserved for the hardest builds; the slowest and most credit-intensive option. Higher levels use more capable models and more AI credits, so Quick is ideal when you only need a fast adjustment, while Savant is there when even Genius is not enough. The App Builder keeps working the same way no matter which level you choose. ### App Builder now catches frozen previews automatically *September 7, 2026* — **If an app preview stops responding in the App Builder, the editor notices and offers recovery options before the browser does** The App Builder now watches the live preview while it runs and detects when it becomes unresponsive. Instead of the whole tab locking up, you see a clear **“Preview stopped responding”** message with four choices: - **Wait** — hide the notice and give the app a little more time; it keeps running in the background and may recover on its own. - **Restart preview** — reload the app from scratch if waiting did not help. - **Turn Safe Mode on** — disable the preview entirely so you can edit the code and chat with the Builder without the frozen app getting in the way. - **Ask the Builder to fix it** — send the App Builder agent the freeze time and recent console output, so it knows exactly what went wrong and can suggest a fix. The editor stays usable the whole time: you can still switch tabs, edit files, and continue the conversation while the notice is shown. Once a preview has frozen, the Builder will not embed it directly in the editor page again, so a runaway app cannot freeze the whole workspace. ### App Builder pages and public apps *September 6, 2026* — **Pro apps can now have multiple pages, including public pages that anyone can visit without signing in** Apps built with the App Builder are no longer limited to a single screen. You can now add extra pages, each with its own address and access mode, so the same app can host both internal ERP tools and public-facing content. This makes it practical to build anonymous-access websites such as landing pages, product catalogs, or registration forms directly inside Operator. - **Each page gets its own path** — for example `/pricing`, `/docs`, or `/register`. Sub-pages are organized as nested paths. - **Public pages need no login** — visitors can open and share the address without an Operator account or an ERP.net connection. - **Internal pages stay protected** — pages that require an Operator user or an ERP.net internal user still ask for sign-in, so one app can mix public and private content safely. - **The Home page sets the default** — you choose whether the app opens publicly or internally by default, and new pages inherit that choice unless you change it. - **Public pages use safe backend requests only** — they can call backend web requests that you explicitly mark as public, but they cannot reach ERP.net data, app tables, files, or secrets directly. To add a page, open an app in the App Builder and go to **Backend → Pages**. Public pages require a Pro app. ### App Builder now runs big jobs as a step-by-step work plan *September 4, 2026* — **Large app changes no longer restart from scratch when a build spans several turns** When you ask the App Builder for something substantial — a multi-file refactor, a performance analysis, or a complex new feature — it now breaks the work into an ordered plan and works through it one step at a time. You see the plan right inside the conversation as a compact **Work plan** strip. - **Progress you can read at a glance** — the strip shows how many steps are done and which one is active, so you know exactly where the build stands. - **Each step finishes before the next begins** — the Builder completes one focused piece of work, records what it found, and only then moves on. - **Pauses resume where they left off** — if a long build is interrupted or needs a Continue, the next turn picks up the pending step instead of rediscovering everything from the start. - **Less wasted context** — findings from completed steps are carried forward, so the same question does not get answered again and again. - **Big jobs become steadier** — refactors, optimizations and large new screens are less likely to drift or lose momentum halfway through. The work plan appears automatically whenever the App Builder decides a request is large enough to benefit from it. You do not need to manage the steps yourself; just describe what you want and watch the plan update as the Builder works through it. --- # August 2026 Updates released in August 2026. ### Every email an agent sends is clearly marked as AI-written *August 30, 2026* — **Automatic AI identification on all agent email, in line with the EU AI Act** When an agent sends, replies to, or forwards an email on your behalf, it now always says so. Nothing to configure — identification applies to every agent, every mailbox, on both Microsoft 365 and Gmail. - **Clear disclosure for recipients** — a short line at the top of the message states that it was generated by AI, and a footer carries a verification link. - **The sender is never presented as a person** — emails come from an identity like *"Anna — AI Assistant of Ivan Petrov"*, never plain *Ivan Petrov*. Acting for someone is never the same as being that person, and the platform now enforces the distinction. - **Replies still reach a human** — replies are routed to the responsible person's address, so recipients always have someone to answer. - **Signed verification** — every message has its own verification page where anyone can confirm it was AI-generated, which agent wrote it, and when — without exposing the message content or recipients. - **Machine-readable, too** — messages carry standard markers so mail clients, filters and compliance tools can detect AI-generated mail automatically. Learn more in [AI Identification in Email](/help/ai-email-disclosure). ### Agents can start working on their own with Activation triggers *August 30, 2026* — **The new Activation tab turns agents into proactive workers** Until now, every agent waited for you to start the conversation. The new **Activation** tab in the agent editor lets an agent wake up and act on its own — on a schedule, on an event, or on an incoming webhook. - **Scheduled runs** — set an agent to work every morning, every Monday, or on any repeating schedule. It opens its task and reports back like any other conversation. - **Event-driven** — when something happens in a connected system, the right agent is triggered automatically and takes care of it. - **Webhooks** — external systems can trigger an agent with a simple call, so incoming requests get handled without anyone watching the inbox. - **One task at a time** — triggers for the same agent are processed in order, so two runs never step on each other. - **Actions that need your approval wait for you** — if a background run reaches a step such as sending an email, it pauses, notifies you, and shows the approval card in the conversation. Unanswered approvals are cancelled automatically after 24 hours so nothing stays pending forever. You find Activation where Triggers used to be — renamed and, more importantly, now fully working. *August 25, 2026* — **Agents can now summarize and group data** Until now, a question like "what did we sell per month, per customer, last year" meant pulling thousands of records. Agents now use the new summarization API in ERP.net 27 to ask the business platform for counts, sums and grouped totals directly, and receive only the result. - **Answers over big data sets** — totals, counts, minimum and maximum values are calculated on the server, so a question spanning a whole year answers in one step. - **Grouping the way a report would** — group by customer, product, warehouse, status or responsible person, and combine several groupings at once. - **Time series out of the box** — group by year, year-month or exact date to get trends, comparisons and "this month versus last month" answers. - **Filter first, then summarize** — the usual filters still apply, so you can narrow to a period, a company or a document type before the totals are calculated. - **Cheaper and faster** — because only the summary travels back, answers arrive quicker and use far fewer AI credits than reading the underlying records. Ask things like: - "Sales per month for 2025, by product group." - "Top 10 customers by total invoiced amount this quarter." - "How many open orders per warehouse, and what is their total value?" - "Largest order value per supplier over the last 6 months." Agents choose automatically between a normal data query — when you need the actual records — and a summary, when you need numbers about many records. ### BI-style apps in the App Builder *August 25, 2026* — **Build dashboards and charts that stay fast on any data volume** The same summarizing power is available to apps, so the App Builder can now produce real analytical applications. - **Dashboards with live figures** — KPI tiles, totals and counters read a single summarized result instead of downloading records. - **Charts and trends** — monthly revenue lines, per-branch bar charts, share-of-total breakdowns and period comparisons. - **Drill-down** — start from a summary, then let the user open the underlying documents for a single group. - **Built for scale** — an app over hundreds of thousands of documents stays responsive because the heavy work happens on the business platform. Just describe what you want to see — "a dashboard with sales per month and per salesperson, with a filter by branch" — and the App Builder will assemble it. **Requirement:** summarizing works with ERP.net version 27 and above. Agents and the App Builder are aware of the version of the connected instance and will fall back to regular queries when it is older, so nothing breaks on earlier versions. ### Meet Digital Entities — agents that keep working on their own *August 17, 2026* — **A new kind of agent that remembers, watches, and acts even when you are not around** Digital Entities are the next step up from regular agents. A normal agent waits for your question; a Digital Entity keeps watching, remembers what matters, and steps in when something needs attention. - **They never forget the important stuff** — facts, tasks, deadlines, and open issues stay alive across days and weeks, so nothing falls through the cracks. - **They notice what did not happen** — a customer reply that never arrived, a delivery that missed its window, a deadline that is quietly approaching. - **They work on their own rhythm** — set them to watch a process, a customer, or a list of obligations and they keep checking back. - **They take initiative** — when they spot something that needs action, they can warn you, start a task, or record what happened. Use a Digital Entity to: - Track contractual deadlines and warn you before they slip. - Follow up on customers who have not replied in a set number of days. - Monitor stock levels, orders, or support tickets that need attention. - Work through a long follow-up list and report progress each morning. Digital Entities are available as an upgrade for any agent. While active, they use 2 AI credits per day. ### Installable apps have a new address *August 15, 2026* — **Apps you install now live at app.operator.net** Apps opened full-screen or installed on a phone or desktop now use a shorter, cleaner address at `app.operator.net`. - **Old links keep working** — anything you bookmarked or shared previously is forwarded to the new address automatically. - **One-time reinstall for a clean icon** — if you installed an app before this change, uninstall it once from your browser's app menu and install it again from the app's full-screen page. Everything else stays exactly as it was. ### More room and better records for Pro apps *August 7, 2026* — **Bigger file limits, retirable records, automatic history and a business date** The app backend got a round of upgrades that make it usable for real, growing data sets. - **More room for files** — an app can now keep up to 500 stored files and 100 MB in total, instead of 50 files and 50 MB. The 5 MB limit per file stays the same. - **Retire records instead of deleting them** — every record now has an **Active** switch. Lists show only the active ones, a direct lookup still finds a retired record, and retired records can be shown again at any time from the **Backend** tab. - **Who changed what, and when** — every record keeps the moment it was created and last changed, together with the user behind each change. It is filled in automatically, so "added today" and "recently changed" lists are instant. - **A business date per table** — a table can now carry one named date that matters to the business: document date, activity date, due date. Date ranges and newest-first lists on it stay fast however large the table grows. - **Steadier record addresses** — apps now give each record a permanent address of their own instead of reusing a business code that may later change. Codes stay editable without creating duplicates, while genuinely permanent identifiers are still used as the address where that helps. ### Pro apps can call external services safely *August 5, 2026* — **Secrets and web requests are now part of the app backend** Pro apps can now talk to other systems — a courier API, a payment provider, a partner platform — without ever holding the credentials. - **Write-only secrets** — store API keys, client ids and secrets in the app backend. They can be set and replaced, but never read back: not by you, not by the App Builder, not by the running app. - **One secret, many customers** — every secret can have a global value plus a value for a specific ERP.net instance. When the app runs on that instance its own value is used automatically, with the global one as fallback. - **Requests defined once, called by name** — the address, headers, body and credentials live in the backend. The app just says which request to run and passes a few parameters, so it can never be redirected elsewhere. - **Logins handled for you** — bearer tokens, basic authentication and OAuth2 client credentials are supported, with access tokens fetched, reused and renewed behind the scenes. - **Test before you ship** — run any request from the **Backend** tab and see the response with all credentials hidden. Both sections live in the **Backend** tab of Pro apps, next to Files and Tables. ### Pro apps can keep their own records *August 3, 2026* — **Pro apps now have their own table storage** Apps on the Pro tier can now store structured records of their own — orders, settings, drafts, favourites, checklists — without pushing anything into ERP.net. Just tell the App Builder what the app should remember and it takes care of the rest. - **Records that belong to the app** — anything that is not ERP.net business data and not an uploaded document now has a proper home. - **Ask in plain language** — *"keep a list of the daily requests"*, *"remember my last selection"*, *"save this form so I can finish it later"*. - **Grouped and searchable** — rows can be grouped (by month, category, customer…) and searched by their display name, so lists and reports stay fast even when they grow. - **Per instance or shared** — a table can keep separate records for each ERP.net instance, or one shared set for the whole app. - **Read-only tables** — mark reference data such as price lists or statuses as read-only so the running app can read it but never change it. - **Browse and edit from the App Builder** — the **Backend → Tables** section lists every table with its rows, a search box, and the full content of any row. - **Generous limits** — up to 100 000 rows per table and 200 000 rows per app. Table storage is available for Pro apps, next to stored files, in the **Backend** tab. --- # July 2026 Updates released in July 2026. ### Pro apps can store and manage files *July 31, 2026* — **Pro apps now have managed file storage** Apps on the Pro tier can now store files in the managed backend. This is the first building block of the Pro managed backend, which will later add secrets, server procedures, an HTTP proxy, persistent logging, public access, and custom domains. - **Store files for your app** — upload files from the App Builder and read them from the app at runtime. Useful for configuration, templates, reference data, or generated reports. - **Clear limits** — up to 50 files, 5 MB per file, and 50 MB total per app. - **Read-only files** — mark files as read-only so the app can read but not overwrite or delete them. Good for configuration and reference data. - **Controlled runtime creation** — choose whether the app can create new files at runtime, or only read and overwrite files you uploaded in advance. - **Private by default** — files are isolated per app and stored in Operator's managed storage. - **Just ask the App Builder** — describe the file the app should read or produce and the Builder wires it up for you. The feature is available in the new **Backend** tab in the App Builder, visible only for Pro apps. ### Apps built with App Builder can now open and host each other *July 30, 2026* — **Apps built with the App Builder can now open and host other apps** Your apps are no longer isolated. An app can now open another app directly, or even host it inside its own UI, so you can build dashboards and hubs that pull together several apps in one place. - **Open another app by name** — tell the App Builder *"open the Customer 360 app when I click this row"* and it wires up the navigation for you. - **Host apps inside other apps** — a dashboard app can show another app as a panel, keeping both apps running and connected to the same ERP.net instance. - **Works everywhere** — app-to-app navigation and hosting work in the App Builder preview, full-screen mode, and installed PWAs. - **No republishing needed** — existing apps can use the new capabilities as soon as you add the behavior in Design mode. ### App Builder now uses far fewer credits *July 29, 2026* — **Building and editing apps now consumes 2× to 5× fewer AI credits** The App Builder has become significantly more efficient. A set of recent improvements work together to reduce the amount of context the AI has to process on every turn, which means your credits go much further when you iterate on an app. - **Cheaper refinements** — small tweaks, style changes, and follow-up requests now cost a fraction of what they used to. - **Faster iterations** — the Builder keeps the relevant context in memory and reuses it instead of reloading everything each time. - **More room to experiment** — because each edit uses fewer credits, you can try more variations before you notice the impact on your budget. Existing apps benefit automatically. You do not need to republish or change anything; the next time you open an app in Design mode and ask for a change, you should see the difference. ### App Builder now creates installable apps *July 24, 2026* — **Every app you build can be installed as its own full-screen app on phones and desktops** Apps built in the App Builder are now real installable apps. Each one gets its own icon and launches in its own window, separate from the main Operator experience. - **Each app is its own install** — installing "Color CRM" or "Delivery Analysis" creates a separate app with its own name and icon. Different apps, and even the same app on different ERP.net instances, are treated as separate installs. - **Generated app icons** — every app gets a unique icon that belongs to the same Operator visual family: a rounded tile with the app initials and a color generated from the app name. - **Full-screen, no browser chrome** — installed apps launch in their own window and behave like native apps on mobile and desktop. - **Install from any share link** — open an app someone shared with you, switch to full-screen, and the browser will offer to install it. The install prompt uses the app name and icon, not the Operator ones. This is available for any app that supports full-screen mode. Users do not need to republish the app; the install option appears automatically. ### Manage Instance hub *July 24, 2026* — **A single home for everything that belongs to an ERP.net instance** Instance management is now centered around a new **Manage Instance** hub. Instead of hunting through menus, admins and power users land on one page that shows the health of the instance and offers one-click access to every management area. - **One hub, every management page** — open the instance selector in the top bar and choose **Manage *Instance*...** to reach the hub. From there you can jump to: - **Users & Permissions** — manage instance users and permission policies. - **Entity Instructions** — teach the AI how your company uses specific ERP.net entities. - **Organizational Capabilities** — connect MCP servers with custom tools and data sources. - **Credit Management** — view and top up the instance's AI credit budget. - **Spend Statistics** — explore where credits are going (see below). - **Live counts on every card** — the hub shows the number of instance users, entity instructions, connected MCP servers, and the credits remaining for the instance, so you can see the state at a glance. - **Faster navigation** — the hub replaces the older flat menu with the same card pattern used by the Admin and Sales areas, making it easier to discover and switch between tasks. The hub is visible to instance Power Users and Admins. Ordinary users continue to use the instance without needing to open the management pages. ### Spend Statistics *July 24, 2026* — **See exactly how AI credits are consumed across your instance** A new **Spend Statistics** page gives instance admins a clear, month-by-month breakdown of credit consumption. It answers questions like *"Which app used the most credits in June?"* or *"Who is driving the spend on the ERP Advisor agent?"* - **Tree view: Instance → Project → User** — the list starts with the target instance, expands into projects (apps, sites, or agents), and then into individual users. - **Six months of history** — each row shows credit usage for the last six calendar months, including the current month, plus a total across the period. - **Project kind badges** — apps, sites, and agents are marked with small badges so you can tell the source of spend at a glance. Built-in agents are shown with their friendly names. - **From the hub** — open it from the **Manage Instance** hub card, which also previews the current month's total spend. Spend Statistics is available to instance Power Users and Admins. ### App Logs *July 23, 2026* — **Persistent app event logs — a structured, queryable log for every app** Your apps now have a real logging channel of their own. Alongside browser console output and low-level ERP API calls, apps can emit **structured events** that are stored on the server, searchable, and available to both you and the App Builder for later analysis. - **Three log streams, one place to view them** — open an app's **⋯ menu → Logs** to see: - **ERP API** — every Domain API call the app makes through the proxy. Optional and time-boxed: enable it on the app for a defined window when you need to trace a specific issue, and it turns itself off automatically. - **App events** — the new persistent, structured log written by the app itself (see below). Stored for 3 days, searchable, and shared with the App Builder. - **Console** — a live mirror of the app's browser console output. Session-only, never sent to the server; great for real-time debugging while you're using the app. - **Ask the App Builder to log the important things** — say things like *"log a warning when the discount is over 20%"*, *"log an error if the invoice fails to save, with the customer id"*, or *"log info every time a report is exported"*. The Builder wires the log calls into the right places for you. - **Structured, not just text** — each entry has a level (info / warn / error), a short message, and an optional JSON payload with whatever context matters (ids, amounts, user choices…). You can filter and search by any of it. - **Click any entry for the full detail** — long URLs, request/response bodies, arguments and errors open in a copyable, monospace dialog — no more truncated text. - **The App Builder reads the same logs** — when you tell the Builder *"the export sometimes fails, please investigate"*, it queries the app's own event log and uses the entries to diagnose the behaviour. You don't have to open the Logs tab yourself unless you want to. - **Safe by default** — App events are visible to the app's owner and admins only. Quotas keep noisy apps from filling the log (roughly 1,000 events per day and 60 per minute per app), and entries auto-expire after 3 days. **When to use which log** - Use **App events** for anything you want to keep, search, or have the AI analyze later — business actions, unusual conditions, failures with context. - Use **ERP API** logging when you're specifically troubleshooting how the app talks to ERP.net. Turn it on for a limited window, then let it switch off. - Use **Console** for live, in-the-moment debugging while you have the app open. Nothing is persisted. You don't need to view the logs yourself to benefit from them — just ask the App Builder to look. The tab is there for when you want to see what's happening with your own eyes. --- # June 2026 Updates released in June 2026. ### Community Sharing *June 28, 2026* — **Community Sharing Platform — share and discover packages of apps and agents** The Community is now open. Publish packages that bundle your apps and agents, or install packages built by other users, all from the new Community area. - **Browse packages** — explore community listings by category, search by title or summary, and preview what's inside before installing. - **One-click installs** — install a package for yourself or, if you're an instance admin, for everyone on your instance. - **Publish your own packages** — bundle apps and agents you own, add descriptions and categories, and submit them for review. - **Approval and install requests** — choose whether anyone can install your packages or each request requires your approval. - **Author notifications** — stay informed about approvals, rejections, install requests, and messages from moderators. Full guide: [Community Sharing Platform](/help/community). ### Profile Page *June 28, 2026* — **New Profile page — see your account, role, and home connection in one place** The user menu now opens a dedicated **Profile** page that gathers your account details and main connection status in a single view. - **Click your name or avatar** anywhere in the user menu to open your profile. - **Account summary** — see your email, display name, and global role at a glance. - **Home connection status** — check which ERP.net instance is set as your home connection and whether it is currently active, expired, or disconnected. - **Quick links** — jump to your instances, notifications, or sign out from the same page. ### Notifications *June 26, 2026* — **Stay on top of background activity and shared items** A new bell icon in the top bar keeps you informed about background activity and items others share with you, so you can leave a long run going and come back when it's done. - **Background and long-running agent runs** — get notified when an execution finishes, fails, or pauses waiting for you to confirm an action. Short runs you watch live don't add noise. - **Sharing** — see when someone shares an agent or an app with you. - **One click to open** — every notification links straight to the related conversation, agent, or app. - **Read, dismiss, mark all as read** — manage items from the bell popover or the full **Notifications** page. - **Optional pop-up toasts** — get a brief corner pop-up when something new arrives; turn it off if you prefer the quieter bell-only experience. - **Mute categories you don't care about** — silence executions, sharing, or system messages independently. - **Automatic cleanup** — read items are kept for 30 days, dismissed items for 7 days, and anything older than 90 days is removed. Full guide: [Notifications](/help/notifications). ### Persistent Attachments *June 24, 2026* — **File attachments now travel with the conversation for up to 3 days** When you upload a file to a chat, the AI can now reference it again in later messages without you re-uploading it. - **One upload, multiple turns** — PDFs, images, spreadsheets, and other attachments stay available throughout the conversation. - **Works across messages** — ask follow-up questions about the same file in a new message and the AI still has access to it. - **Stored for up to 3 days** — attachments remain linked to the conversation so you can keep working from them during an active session. ### Lock Icon in Builders *June 19, 2026* — **App Builder and Agent Builder now respect the lock icon** The lock icon in the chat input now controls whether the AI can make changes in App Builder and Agent Builder conversations. It has also moved from the header to the chat input box for quicker access, and you can toggle it with **F8**. - **Locked (read-only) mode** — the AI can discuss ideas, inspect files, and explain what it would do, but it will not create, edit, or delete apps, agents, or files. Use this when you want to review or ask "what if" questions safely. - **Unlocked (read-write) mode** — the AI can apply changes to apps and agents as you describe them. - **Sensitive actions still ask first** — destructive actions, such as deleting a file, continue to show a confirmation before they run, even in read-write mode. ### Agent Builder *June 18, 2026* — **Build your own agents through chat** Designing a user-defined agent is now a conversation. Pick **Agent Builder** from the agent selector, describe what you want, and the agent is created and refined live as you talk to it. - **Open the builder right from a chat with your agent** — as the agent owner, press **F2** or click the wand icon in the chat input to switch any user-defined agent conversation into the Agent Builder and keep refining the agent in the same thread. - **Chat on the left, live preview on the right** — instructions, greeting, welcome screen, capabilities, and diagram all update as the conversation evolves. - **Agent or Process, chosen from your wording** — phrases like *"assistant that…"* or *"agent that can…"* create a runnable Agent; *"diagram"*, *"SOP"*, *"checklist"*, *"playbook"*, *"runbook"* create a non-runnable Process. You can flip the Kind later. - **Keep iterating in the same conversation** — say things like *"shorten the instructions"*, *"add a button that opens the sales dashboard"*, or *"switch the base agent to System Architect"* and the Builder updates the agent in place. - **AI-generated flow diagram** — every agent gets a diagram of its data flow, capabilities, and the Domain API entities it touches; regenerate with hints, export to PNG, or zoom and pan to explore. - **Welcome screen WYSIWYG** — edit the greeting message and quick-action buttons inline on a preview of what your end users will see. - **Manual edits any time** — every field is also editable directly in the side panel when you'd rather tweak by hand than ask for it in chat. - **Bookmarkable design sessions** — the latest design conversation for an agent reopens automatically; past sessions are one click away from the **Conversations** tab. Full guides: [Agents](/help/agents) · [Creating Agents](/help/agents-creating) · [Working with Diagrams](/help/agent-diagrams). ### Version History *June 14, 2026* — **Version history and restore for apps and agents** Every meaningful change to an app or a user agent is now captured as a restorable version, so you can roll back instantly when an AI build turn goes the wrong way. - **Auto-snapshots on every AI turn** — completed App Builder and Agent Builder turns are saved automatically (duplicates are skipped). - **Manual checkpoints with labels** — click *Save current version* to pin a named baseline; labeled versions are kept forever. - **One-click Restore** — choose **Replace** to overwrite in place (a pre-restore snapshot is saved first, so it's reversible) or **Duplicate** to clone the chosen version into a brand-new app or agent. - **Sensible retention** — the 50 most recent unlabeled snapshots are kept per app/agent; all labeled ones stay forever. - **Where to find it** — *Version history* in the App Builder's Properties, and the *History* button at the top of the Agent Builder panel. ### Agent Optimization *June 11, 2026* — **Make your agents faster, cheaper, and more accurate** User-defined agents can now be **optimized per ERP instance**. A dedicated analyzer session explores the agent's instructions once, resolves the names you mentioned (products, customers, stores, document types…) to ERP IDs, captures the exact schemas of every entity the agent will touch, and pre-loads the relevant data-management instructions. Every later conversation with that agent boots with this knowledge already in context. - **Faster first turns** — no more re-running entity discovery, schema lookups, or instruction tools on every new chat. - **Lower credit usage** — the design-time work happens once per instance instead of once per conversation. - **Fewer payload mistakes** — each attribute's exact type is captured up front, so the runtime agent stops confusing plain text fields with multilingual ones, or dates with date-and-time values. - **Per-instance, safe to re-run** — optimize for instance A without touching instance B; switch instances from the top bar and re-run any time your instructions, capabilities, or ERP IDs change. - **Read-only by design** — the optimization session cannot create, update, or delete anything; only discovery tools run. - **Server-validated artifact** — saves are rejected if the optimizer skipped a required schema or instruction, and the session is asked to fill the gap and try again. Open any agent → **Optimization** tab and click **Optimize** on the current instance to try it. Full guide: [Agent Optimization](/help/agent-optimization). ### App Builder Conversations *June 8, 2026* — **Multiple conversations per app, with archiving** Each app now supports **multiple parallel conversations** so you can split building work into focused threads instead of one ever-growing chat. Open the new **Conversations** tab in the app panel to see them all. - **One conversation per feature or sub-project** — keep "checkout flow", "admin settings", and "bulk import" in separate threads so the AI stays on-topic and prompts stay short. - **Smaller, faster, cheaper turns** — shorter histories mean lower credit usage and quicker responses on every prompt. - **Switch with one click** — every conversation for the current app on your active instance is one click away; conversations on other instances are shown for reference and open after you switch instance. - **Created & updated timestamps** — see at a glance when each conversation was started and when it last had activity. - **Archive what you're done with** — hide finished conversations from the default view with the row menu, and bring them back any time via **Show archived → Restore**. Nothing is deleted. - **New conversation** — the top-right button starts a clean thread for the same app on your current instance and drops you straight into the Design view. Full walkthrough and example flow: [Conversations](/help/builder-conversations). ### Longer Builds *June 7, 2026* — **App Builder: longer uninterrupted builds (up to 15 minutes)** App Builder prompts now run for **up to 15 minutes** before pausing to ask you to continue — up from about 4 minutes previously. Larger, more complex apps can be built in fewer prompts, with fewer interruptions in the middle of a turn. - **Bigger scope per prompt** — multi-screen layouts, richer data wiring, and broader refactors can now complete in a single request. - **Fewer "Continue" pauses** — the builder keeps working through long-running steps instead of stopping early. - **Automatic for every App Builder conversation** — no setting to flip; it's on by default whenever you're in the App Builder. ### Per-Instance App Threads *June 6, 2026* — **A separate App Builder conversation per ERP instance** Each app now keeps a **distinct build conversation for every ERP.net instance** you connect with, so switching instances never mixes work across them. - **Open an app on a given instance** — the App Builder loads the conversation previously used to build that app *on that instance*. If none exists yet, it starts a fresh one as soon as you type. - **Switch the active instance from the top bar** — the Design/Code view immediately swaps to that instance's conversation for the same app (or a clean slate if there isn't one yet). The instance selector and the conversation now always agree. - **No more cross-instance prompts** — you'll no longer be asked to reconnect to a different instance just because an older conversation for the app happened to be bound to it. - **Active builds aren't interrupted** — if a build is mid-stream when you switch the instance, the running conversation stays put until it finishes. --- --- # May 2026 Updates released in May 2026. ### Duplicate Apps *May 30, 2026 — App Builder: duplicate any app you can clone* You can now make your own copy of an app from a single dialog, with sensible defaults that keep your apps list tidy. - **Duplicate from two places** — the actions menu (⋯) on each card on the **/apps** page, and a new **Duplicate** button in the *Duplicate App* section of an app's **Properties** tab. - **Name and slug you can edit** — a confirmation dialog opens with both fields pre-filled. The defaults append today's date (e.g. *"My App (2026-05-30)"* and *"my-app-2026-05-30"*), and add a numeric suffix if a collision is detected (`… (2)`, `…-2`, and so on). - **No stacked dates** — if the source app already ends with a date suffix, that date is replaced rather than appended again. - **Clean copy** — files, description, categories, form factor and safe-mode flag are copied; sharing, Web Client integrations, conversations, statistics and deployments are not. You land straight in Design mode for the new app. - **Permission required** — works on apps you own or that have been shared with you at **Clone** level or higher. See [**Managing Apps**](/help/app-builder-management) under *Build Apps* in the help. ### Reference Other Apps *May 30, 2026 — App Builder: reference another app to copy code across* The App Builder agent can now look at the files of another app you have access to, and adapt them into the app you are building. - **Type `@` in the chat** — a popover lists the apps you can reference (anything shared with you at **Clone** level or higher, excluding the current app). Pick one and the editor inserts an `@app:` mention. - **Read-only on the source** — the agent can list and read the referenced app's files, but never write to it. Anything it copies is written into the **current** app, the same as any other build step. - **Just describe what you want** — *"adapt the dashboard layout from @app:sales-overview into this app"* is enough; the agent will fetch the relevant files and bring them over. See [**AI in Apps**](/help/app-builder-ai) under *Build Apps* in the help. ### Device Form Factors *May 22, 2026 — App Builder: design for phone, tablet, desktop, or wide screen* You can now tell the App Builder which device shape your app is meant for, and the preview resizes to match — similar to the device mode in a browser's developer tools. - **Display form** — a new property on every app with four choices: *Phone*, *Tablet*, *Desktop*, and *Wide screen*, each labelled with its target pixel size. - **Preview matches the choice** — the preview area centres your app on a stage of the chosen size, with scrolling when it doesn't fit, so you see exactly how it will look on that device. - **Just ask the agent** — saying *"make me a mobile app"* or *"design this for tablet"* is enough; the App Builder switches the display form for you. - **Saved per app** — the choice sticks across sessions. The standalone, deployed app still uses the real device viewport of whoever opens it. See [**Managing Apps**](/help/app-builder-management) under *Build Apps* in the help for the full list of properties. ### Bearer Token Auth *May 22, 2026 — MCP Servers: connect using a Bearer token* You can now add an MCP server that needs a personal API key (such as Render's `https://mcp.render.com/mcp`) directly from the Capabilities page. - **New authentication option** — the **Authentication** field offers a third choice, **Bearer token**, alongside *No authentication* and *Send user's instance token*. - **Paste once, use everywhere** — drop the key into the new **Bearer token** field; every call to that MCP server is sent with the token automatically. - **Stored securely** — the token is kept with the rest of the server's configuration and is never shown back in plain text after saving. See [**Organizational Capabilities**](/help/mcp-servers) under *Build Agents* in the help. ### Safe Mode *May 20, 2026 — App Builder: Safe Mode for recovering frozen apps* A custom app whose preview hangs or loops can now be opened **without running its preview**, so you can fix it instead of losing it. - The Apps page actions now live in a single overflow menu, with two new entries: - **Open in Safe Mode** — a one-time rescue for the current tab. The next normal open runs the preview again. - **Switch to Safe Mode** — keeps the app in Safe Mode permanently, until you turn it off. - In Safe Mode, the preview area shows a clear placeholder telling you whether it is *one-time* or *permanent*. The **Code** tab and **chat** keep working, so you can edit files or ask the agent to revert. - A matching switch in **Properties** controls the permanent mode and shows a notice when a one-time session is the reason the preview is hidden. - Apps that are permanently in Safe Mode get a **Safe Mode** badge in the apps list. See [**Safe Mode**](/help/app-builder-safe-mode) under *Build Apps* in the help for the full walkthrough. ### Delegation Polish *May 19, 2026 — Agent Delegation: clearer waiting state and more reliable finishes* Follow-up polish for the Agent Delegation feature shipped on May 18. - A clear **"Waiting for sub-agents…"** indicator now shows for the whole time the main conversation is waiting on its helpers, with a spinner on each one — so it no longer looks stuck while they are still working in the background. - The *"this execution looks stuck"* warning is hidden while any helper is still running, removing a false alarm that could appear during a resume. - Helpers that run in the background no longer get incorrectly reported as failed when they actually completed successfully — the main conversation now consistently sees the real result and summary. ### Agent Delegation *May 18, 2026 — Agents can now split work across helpers* Agents can now hand parts of a job to other agents you have created — or to copies of themselves — and bring back the combined results. - **Off by default.** Turn it on per agent from the **Capabilities** page. Available on a few of the more advanced built-in agents that typically coordinate larger pieces of work. - **Big jobs fit.** Each piece runs in its own conversation, so long or context-heavy work no longer has to squeeze into a single run. If helpers are still busy when the main agent checks in, it simply waits and tries again. - **Live status.** The main conversation shows a card per helper — *running*, *waiting for confirmation*, *completed*, *failed* — that you can expand to read its full transcript. - **Stays in your control.** Anything sensitive a helper tries to do still surfaces in your main conversation for your approval. - **Limits for now.** Only your own custom agents can be targets. Up to five helpers per call, and helpers cannot themselves dispatch further helpers. See [**Delegation & Sub-Agents**](/help/agent-delegation) under *Build Agents* in the help for the full walkthrough. ### App Statistics *May 17, 2026 — See exactly what each app costs and who uses it* - Every app in the App Builder now has a new **Statistics** tab with a full breakdown of its activity. Three top cards split AI credit usage by mode: **Design** (credits you spent building the app in the App Builder), **Execution** (credits the app itself consumed when run by users) and **Usage** (unique users, total opens, opens this month, instances and last-opened timestamp). Each credit number is shown together with its approximate EUR value, using the same per-credit price as the Automations stats so the figures stay consistent across the product. Below the cards, two horizontal bar charts — **Lifetime by instance** and **This month by instance** — group **unique users** and **activations** per ERP instance, with one row per instance so the chart scales cleanly as more instances adopt the app. Click a legend entry (Users / Activations) to toggle that series on or off. ### Per-Tab Active Instance *May 6, 2026 — Active instance is now remembered per browser tab — and across sessions* - Your active instance connection now follows the same persistence model as the agent picker: it's stored both per-tab (so two tabs can be on different instances independently) and as your cross-session default in your profile (so a brand-new tab opens on the instance you last picked from Home). Picking an instance from the Home screen ("New" mode) updates both — that becomes the new default. Loading an old conversation no longer changes which instance the **New** button picks: the instance selector goes read-only and just shows the connection that conversation is bound to, while your home instance is preserved untouched. Pressing **New** restores it. ### Conversation Properties *May 6, 2026 — Inspect the metadata of any conversation* - The conversation's overflow menu (⋯ in the conversation history sidebar, plus the right-click / long-press context menu) now has a **Properties** action. It opens a dialog showing the full metadata of the conversation: title, ID, status, type, created/updated timestamps, agent (resolved to its user-friendly name), instance, connection ID, reasoning level, app/site IDs, capabilities, unlocked tools, auto-approved capabilities, and — when applicable — the failure reason and details. Useful for debugging, support requests, and confirming which agent / instance / capabilities a conversation is actually bound to. ### Per-Connection Budget *May 5, 2026 — Pick who pays for each connection's AI credits* - Each instance connection can now choose which budget pays for its AI usage: your **Home connection** pool (the default) or **This instance** — the per-instance balance an admin allocated to you on that instance. Edit a connection on `/my-instance-connections` and a new **AI credit budget** section appears with both options and live balances for each. The **This instance** option is disabled until an instance admin tops you up there (with the hint *"ask the instance admin to top you up"*). When selected, AI usage on that connection bills the per-instance budget — and if it runs out you get an explicit error rather than a silent fallback to your home pool. Typical use case: an external consultant whose customer wants to fund the consultant's AI usage on the customer's instance directly. The actual debiting ships in a follow-up release. A new **Instance Connections** section in `/help` documents this and the rest of the connection management UI. ### User Credit Budgets *May 4, 2026 — Give individual users their own AI credit balance* - The `/billing-credits` page now has two tabs: **Instance Budgets** (the existing one-time top-up flow that funds an instance pool) and a brand-new **User Budgets** tab where instance admins can manage per-user balances. Credits, once topped up to a user, belong to that user — they don't follow the home connection if it changes later. From the new tab admins can: **(1) Top up now** — move credits from one of their instance pools into a user's personal balance, with a live preview of the pool's remaining credits and the user's monthly headroom; **(2) Edit settings** — set an optional **monthly top-up limit** (cap on how many credits can be moved into the user this calendar month) and configure **auto top-up** (when enabled, picks a threshold + ceiling + source instance — the system will later top the user up to the ceiling whenever their balance falls below the threshold); **(3) View history** — full audit log of every top-up with type (manual / auto / adjustment), source instance, performer and resulting balance. Monthly totals are computed live from the audit log, so they're always in sync. Usage debiting (consumption of these user balances by AI requests) ships in a follow-up release. ### Home Connection *May 4, 2026 — Pick the instance that pays for your AI credits* - Each user now has a single **home connection** among their ERP.net instance connections. The home connection is the one that will be billed for AI credits going forward (the budgeting itself ships in a follow-up). On `/my-instance-connections` your home instance is marked with a small **Home** badge in the **Name** column, and a **Set as home** action has been added to the row's overflow menu (⋯) — picking a new home automatically demotes the previous one. The instance dropdown in the top bar also shows a small home icon next to the home connection so it's identifiable everywhere. When you add your **first ever** connection it becomes home automatically; when you add another internal connection while still having no home, the **Add Instance** dialog offers a *"Set as my home connection"* checkbox (pre-checked). Existing users who currently have exactly one connection were backfilled — that one connection is now their home. Users with multiple connections were left untouched and can pick a home from the overflow menu. ### Download Link Expiry *May 3, 2026 — Code Interpreter: generated file downloads now expire after 3 days* - Files produced by the Code Interpreter (Excel exports, charts, PDFs, etc.) are stored in Operator's private file storage and surfaced as signed download links inside the conversation. Until now those links were valid for 10 years, which meant the storage bucket grew without bound. Each link is now valid for **3 days (72 hours)** from the moment it is generated, and the expiry is shown next to the download (e.g. *"link expires in 3 days"*); once it elapses, the download button in the file card becomes disabled. A nightly cleanup job at 03:15 UTC removes both the expired storage object and its database record, and writes one summary row per run into the **API Logs** viewer under log type **Cleanup** — so admins can spot any failed deletions and the affected paths. If you need a file that has already expired, just re-run the prompt to regenerate it. ### Buy AI Credits *May 2, 2026 — Instance admins can now top up an instance* - Instance admins can now purchase AI credit packages for any ERP.net instance they administer. Open the instance dropdown in the top bar and pick **Buy AI Credits**, or go directly to `/billing-credits`. Four one-time top-up packages are available — 100 credits for €30, 1,000 for €250, 10,000 for €2,200, and 100,000 for €18,000 — with the per-credit price dropping as the package grows. Credits attach to the **instance** (not to a single user), so the whole team shares the same pool. Each top-up is logged in **Purchase history** on the same page. Payments are handled by Stripe; Operator never sees card details. ### App Builder for Power Users *May 1, 2026 — App Builder: now available to instance Power Users* - Until now, the **App Builder** agent required a global **Power User** role in Operator. It is now also available to users who are **Power User** or **Admin** in the currently connected ERP.net instance — even if their global Operator role is just Normal User. The boost is tied to the active instance: disconnect, or switch to an instance where you only have Normal/External access, and the App Builder hides itself again (any in-progress selection falls back to the default agent). Global Power+ users keep unrestricted access regardless of which instance is connected. The same rule gates the **Apps** page and the **Build → Apps** menu entry. ### Auto-Promote Instance Admins *May 1, 2026 — Instance Admins are automatically promoted to Admin in Operator* - Each time you connect to an ERP.net instance, Operator now checks whether you are an admin in that instance and updates your **instance role** to match. If you are an admin in ERP.net, you are promoted to **Instance Admin** in Operator automatically; if you are no longer an admin, your Instance Admin role is dropped to **Power User**. Lower roles aren't touched. This keeps your per-instance permissions in Operator — entity instructions, permission policies, instance user management — aligned with ERP.net without anyone having to assign roles by hand. Every change is recorded in the audit log. --- --- # April 2026 Updates released in April 2026. ### April 29, 2026 **App Builder — generated apps always close Domain API transactions** - The ERP.net Domain API allows only **one open transaction per session**. If an app opened a transaction and an error happened before it closed, every later attempt to start a new transaction failed with *"Maximum allowed transactions for this session have been reached"* until the session expired — effectively breaking the app for the user. The App Builder is now explicitly instructed to (a) avoid transactions when a single write is enough, and (b) whenever a transaction IS used, wrap it in a `try / catch / finally` block that rolls it back on any error path. New apps generated by the App Builder will follow this pattern automatically; existing apps that show the symptom can be regenerated or patched in the App Builder to pick it up. ### April 28, 2026 **Business Specialist — full daily capability set now visible to all users** - Normal users opening **Capabilities** for the **Business Specialist** agent were only seeing 4 of its 10 capabilities (General Knowledge, Entity Schema, Email, Documentation). The other six — **Query Data, Support Tickets, Calendar Management, Document Management, File Management, and Update Data** — were hidden because their per-row level requirement was higher than a normal user's role level. These capabilities are part of the agent's intended default set and require an instance connection to do anything destructive, so the level gate has been removed. Business Specialist now shows all 10 included capabilities for every signed-in user. ### April 28, 2026 **App Sharing — clearer errors and stale-session recovery** - The "Share with Instances" form on an app's **Share** tab was failing for everyone except global admins with a misleading *"Instance not found"* error. The UI was reading the `erpnet_instance_deployments` table directly to resolve the UIN, but that table is locked down (it stores OAuth client secrets) so non-admin reads silently returned nothing. Resolution now goes through a security-definer helper that returns just the deployment id, so any signed-in user can share with any deployed instance whose UIN they know — secrets stay protected. The input field accepts `mycompany`, `mycompany.my.erp.net`, or `https://mycompany.my.erp.net`. - Follow-up: when sharing failed for a different reason — typically an expired sign-in session — the form was still showing the same "Instance not found" toast. The form now refreshes the auth session before the lookup, surfaces the real lookup error if PostgREST rejects the call (e.g. *"JWT expired"*), and only shows "Instance not found" when the deployment genuinely isn't registered. The downstream insert into `user_app_instance_shares` also includes the underlying error message in its toast so RLS rejections are no longer silent. - Follow-up 2: rows in the **Share with Instances** list were displaying the raw deployment GUID for non-admin users because the enrichment query also ran against the locked-down deployments table. The hostname (e.g. `inko.my.erp.net`) is now resolved through a second security-definer helper that returns only the public base URL, so every user sees the friendly instance name they shared with — no OAuth secrets exposed. ### April 28, 2026 **Manage Instance Users — instance admins now see real names and emails** - On `/manage-instance-users`, instance admins were seeing other connected users as **"Unknown User"** with no email. The connection rows were visible, but the linked profile data wasn't — so admins couldn't tell who they were assigning roles or policies to. Instance admins can now read the display name, email, and avatar of any user with a connection on an instance they administer. Visibility is scoped strictly to that instance's connected users; nothing else in the profile table becomes accessible. ### April 28, 2026 **App SDK — `writable: true` no longer blocked by deployment read-only flag** - The deployment-level read-only flag on instance deployments is for **deployment protection** (it locks OAuth credentials and blocks the install/uninstall webhook from overwriting the row). It is **not** a data-write gate. App-SDK conversations that ask for `writable: true` were incorrectly being demoted back to read-only when this flag was set, even though normal chat and automations on the same instance kept writing freely. That override is removed: `writable: true` now means write mode, with per-record authorization still enforced by the user's ERP permissions and any instance permission policies — exactly like normal chat. ### April 28, 2026 **App Builder — image attachments from apps now work (final fix)** - Earlier today's fix only corrected the path for *new* messages. Existing app-SDK messages still had `type: "file"` stored alongside an image MIME type, so the agent kept routing them to the unsupported text-extraction pipeline. The agent now also detects images by MIME type and filename extension, so JPG/PNG/WebP attachments always take the vision path regardless of the stored `type` field. - When an app-SDK execution fails before producing any text, the proxy now returns the actual error string (e.g. *unsupported file type*) instead of an empty response, so apps can show a meaningful message instead of a silent blank. ### April 28, 2026 **App Builder — separate history tab for app-initiated conversations** - Conversations started by an app through the SDK no longer get mixed up with App Builder build conversations. Returning to an app on `/app/:id` now always reopens the build conversation, even if the app launched runtime conversations against the same app. - The history sidebar gets a new **App AI** tab (sparkles icon) listing conversations started by an app via `operator.ai.createConversation`. App building conversations stay in the existing **Apps** tab. ### April 28, 2026 **App Builder — agents see attached files, and can opt into write mode** - When an app passes a file to an agent (via `addMessage({ file })`), the agent now actually **sees the file content** during the run — images, PDFs, spreadsheets, and the rest. Previously the agent ran blind even though the file was correctly stored on the user message. - Conversations launched from an app are **read-only by default**. If your app needs the agent to create or update ERP records, just say so when describing the app (e.g. *"the agent should be able to update records"*) — the App Builder will switch the conversation into write mode for you. Per-record authorization is still enforced by the user's ERP permissions and any instance permission policies. ### April 28, 2026 **App Builder — user agents now run with their own settings** - When an app launches a conversation with one of your own user-defined agents, the conversation now correctly inherits the agent's **base persona**, **reasoning level**, and **capability list**. Previously the conversation fell back to the Advisor base, which capped reasoning at "Fast" and hid the agent's data tools. - Apps can still **narrow** an agent's capability list for a specific use case, but they can never widen it beyond what the agent itself is allowed to use. ### April 28, 2026 **App Builder — agents by name, no UUIDs** - When you tell the App Builder to use one of **your own** agents (or one **shared with you**), it now finds the agent **by name** and wires it into the app for you. End users of the app no longer need to type a "User Agent ID" or paste a UUID anywhere. - Built-in agents (Advisor, Business Specialist, System Architect, Partner, Sales Executive) work the same way — just refer to them by name. - If you mention an agent name the App Builder cannot find, it will ask **you** (the app author) to pick from the list — never the end user. ### April 28, 2026 **App Builder — your apps can now use AI** - When you describe an app, you can ask the App Builder to use AI as part of it. Two flavors are available: - **Pure AI** — fast, one-off thinking. Great for *"classify this message"*, *"summarize these notes"*, *"extract the total from this invoice photo"*, or *"translate this to French"*. You can choose how hard the AI thinks: Fastest, Fast, Smart, or Expert. - **Full agent conversations** — let your app run any Operator agent in the background, exactly like the assistant in the main chat. Pick a built-in agent (**Advisor**, **Business Specialist**, **System Architect**, **Partner**, **Sales Executive**) or one of your **own user-defined agents**, and optionally limit which capabilities it uses inside the app. - Conversations started from an app appear in the user's normal chat history and run against the instance the user has selected in the toolbar. - See the new **[AI in Apps](app-builder-ai)** help topic for examples of what to ask for. ### April 28, 2026 **Permission Policies — AI is warned about restrictions up-front** - When the AI looks up an entity (during normal data discovery), the response now includes the user's effective access — **full**, **read-only**, or **none** — based on the assigned permission policy. The AI uses this to warn you proactively before attempting a query that would be denied, and to avoid retrying similar lookups against entities outside your scope. ### April 28, 2026 **App Builder — self-service support policy documented** - The **[App Builder help](app-builder)** now includes a **Support Policy** section. AI-generated apps follow a self-service model and are not covered by traditional support: you are responsible for testing, security configuration, and accepting the risks of AI-generated code. You always own the code and can export it. ### April 28, 2026 **New help topics: Permission Policies & Topic Guard** - Added a detailed **[Permission Policies](permission-policies)** guide for instance admins, covering the scope tree editor, Read vs Update access, the Allow off-topic switch, assigning policies to users, and how enforcement works alongside ERP.net's own security. - Added a **[Topic Guard](topic-guard)** topic explaining how the setting keeps AI conversations focused on ERP.net work, and what the locked state means when a permission policy controls it. ### April 28, 2026 **Permission Policies — Allow off-topic conversations** - Each Permission Policy now has an **Allow off-topic conversations** switch above the scope tree. - When disabled, users assigned to that policy can only discuss ERP.net and business topics — they won't be able to chat with the AI about unrelated things (e.g. the weather). - For affected users, **Settings → AI-enhanced → Topic guard** is automatically turned on and locked, with a hint explaining that their instance admin controls it. ### April 28, 2026 **Permission Policies — visual tree editor** - The Policies editor in **Manage Instance Users → Policies** is now a single interactive tree of all ERP.net namespaces and entities. - Tick any namespace to grant access to its entire subtree, or expand and pick individual entities. Mixed grants are shown with an indeterminate state. - Pick **Read** or **Update** per branch (Update covers create, update and delete). Search filters the tree and auto-expands matches. - Saving a policy automatically collapses your selection to the smallest equivalent set of scope entries (e.g. a fully-ticked `Crm` branch becomes a single `Crm.*` entry). ### April 28, 2026 **Permission Policies for instance users** - Instance admins can now define **Permission Policies** in **Manage Instance Users → Policies** and assign one to each internal or client user. - Each policy lists scopes (e.g. `Crm.*`, `Logistics.Inventory.*`, `Finance.Accounting.Accounts`) with **Read** or **Update** access (Update covers create, update and delete). - Policies are enforced on top of ERP.net's own security: when an assigned user queries or modifies data, Operator checks the policy first and blocks operations on entities outside the granted scopes. - Users without a policy keep unrestricted Operator-side access (ERP.net security still applies). - Policy assignment changes are recorded in the instance Audit Log. ### April 27, 2026 **Code tab now visible to everyone in App Builder and Site Builder** - The **Code** tab is now available to all users in both the App Builder and Site Builder workspaces, regardless of role level. Previously it was restricted to developer-level accounts. Anyone with access to design an app or work on a site can now inspect the underlying code directly from the workspace. ### April 26, 2026 **Knowledge search now spans all of ERP.net documentation** - "Search documentation/knowledge" now searches the entire ERP.net knowledge corpus in a single call: official Technical, Developer, Presales, Web Client, and Windows Client documentation, the Zendesk knowledge base, system business rules, and every companion app's docs (Bank Sync, Operator, Retail POS, Retail POS Manager, VOX). Previously the assistant could miss articles that lived in the new product-documentation indexes — now they are ranked side-by-side with everything else. - Ranking across all sources is now done in one pass with a unified relevance score, so the most relevant article wins regardless of which source it came from. ### April 26, 2026 **Better knowledge search for non-English questions** - The assistant now searches the English documentation and knowledge base more effectively regardless of the conversation language. When you ask a question in Bulgarian, German, or any other language, the assistant translates the search intent to English before querying — so full-text matching works as designed and you get relevant results instead of an empty response. ERP.net-specific identifiers (rule codes, entity names, error codes) are still passed through verbatim. ### April 26, 2026 **Continue now reliably picks up where the agent stopped** - Previously, after the platform paused a long App Builder run with the "Paused — Continue" prompt, hitting Continue could cause the agent to start reasoning from scratch instead of resuming the prior chain of thought. The first AI call after Continue is now correctly chained to the paused run's last response in every pause case (including platform CPU-time pauses), so the next turn carries the full reasoning context and you don't pay for redundant re-derivation. **In-progress assistant text now survives a paused build, even mid-stream** - Previously, when a long App Builder turn was paused by the platform mid-streaming (the "Paused — Continue" case), any text the assistant was *currently streaming* was lost on reload — the bubble came back empty even though you saw the words appear during the build. (A related fix on Apr 25 covered text from already-completed iterations; this one covers the iteration that was actively streaming when the pause hit.) - The in-progress text is now persisted live as it streams, throttled so it doesn't add overhead to the build. Paused builds reload with everything you saw on screen, and Continue picks up cleanly from there. ### April 25, 2026 **More headroom for heavy agentic loops** - The per-turn time budget for an AI run is now **5 minutes** (up from 4). Heavy agentic loops — many tool calls or large App Builder turns — were hitting the 4-minute ceiling and pausing for Continue when they were still actively making progress. The complementary upstream-silence guard was raised in lockstep to 5 minutes as well. ### April 25, 2026 **Long reasoning turns are no longer prematurely marked as Paused** - The system that detects stalled AI runs now waits **120 seconds** of silence (up from 45) before flagging a run as paused. With the latest reasoning models, a single AI request can legitimately take 60–120 seconds to come back, and the previous threshold was misfiring on perfectly healthy long turns. Genuinely stuck runs are still detected automatically — just within ~2 minutes instead of ~45 seconds. ### April 25, 2026 **Assistant text no longer disappears on reload of a paused build** - When a long App Builder turn was killed mid-stream by the platform CPU limit (the "Paused — Continue" case), the assistant's explanatory text that had streamed visibly during the build was lost on reload — the bubble came back empty even though the file changes and tool-call breadcrumbs were intact. Root cause: the orchestrator only saved per-iteration text into the durable accumulator at the very end of a turn, so any iteration that mixed text + tool calls (the normal builder pattern) had its text dropped if the turn didn't reach the end. The text is now folded into the durable accumulator as soon as each iteration returns, so paused/killed turns reload with the full assistant message intact. - Same fix incidentally repairs an older silent loss on **successful** turns: any text emitted in an iteration that also produced tool calls used to be dropped from the persisted message (only the final tool-free iteration's text was kept). All assistant text from the turn is now preserved. ### April 25, 2026 **Friendlier, action-oriented messages when a turn is interrupted** - Every interruption banner now tells you in plain language **what happened** and **what to do next**, instead of developer-flavored phrases like *"server restarted mid-turn"* or *"isolate killed"*. - The most common case — a long App Builder run hitting the platform's per-turn CPU limit — now consistently shows a neutral **"Paused. This turn ran longer than the platform allows. Your progress is saved — click Continue (or type continue) to pick up where it stopped."** banner with a one-click **Continue** button. - Recoverable failures (AI service stopped responding, connection dropped, rate limited) get an amber **"Try again"** button. Informational failures (browser disconnected, save failed) explain what's intact and what to do next, without a misleading button. - Conversation-list tooltips were rewritten to match — a quick scan of the icons now tells you which threads need a click and which are mid-thought. **Stalled builds recover within ~90 s instead of 3 min** - The background sweeper that flips abandoned builds from "Building app…" to a clear paused/failed state now runs with a 90-second cutoff (was 180 s) for every kind of conversation. The heartbeat-aware fast path still detects platform CPU kills within ~45 s and tags them as `cpu_exceeded` so the friendly Continue banner shows up immediately — no more waiting 3 minutes to know a turn died. ### April 24, 2026 **Long app builds no longer get killed mid-turn by the platform CPU limit** - Several pieces of recently-added background bookkeeping inside the orchestrator (per-event SSE trace inserts, repeated Supabase client construction, double-writing the assistant message every few seconds, JSON deep-cloning all 130+ tool schemas) were quietly piling up isolate CPU on long builder turns. Cumulatively they were the actual cause of the *"server restarted mid-turn"* failures around turn 12–15 — not the AI model or the tools themselves. Trimmed: - SSE trace logging is now **off by default** (still enabled per-deployment via `SSE_TRACE_ENABLED=true` for targeted diagnosis). - The mid-turn assistant-message checkpoint now only fires after a builder write tool (`create_app`, `create_site`, `write_app_file`, `patch_app_file`) — every other turn relies solely on the terminal end-of-turn write, eliminating 10–20 redundant row rewrites per long turn. - Status updates, response-id updates and trace inserts now reuse a single Supabase client per isolate instead of constructing a new one every call. - Tool definitions are no longer deep-cloned on every turn for strict-mode coercion. - When the platform *does* still hit the CPU ceiling, the failed turn now shows a friendly **"Build paused — type continue to keep going"** banner with a one-click Continue button (same flow as the existing work-budget pause), instead of the cryptic "execution failed" badge. ### April 24, 2026 **App and site creation no longer fails on slug collisions** - App and site slugs are globally unique across the platform, so `list_apps` (which only sees the current user's apps) couldn't reliably prevent conflicts. The `create_app` and `create_site` tools now detect a unique-key collision server-side and automatically append the smallest free numeric suffix (`-2`, `-3`, …), retrying up to 5 times to absorb races. The result includes `slug_adjusted: true` and the original `requested_slug`, so the agent can mention the rename to the user — e.g. *"created as 'sales-2' (the slug 'sales' was already taken)"*. No more wasted turns retrying with random suffixes. ### April 24, 2026 **Per-prompt work budget raised so app builds reach completion** - The orchestrator's per-prompt safety limits were tuned for short Q&A turns and were tripping during normal App Builder runs — often before `create_app` was even called. Limits raised to **30 turns**, **30 file writes**, **750 KB written**, and **240 s wall time** per prompt (from 12 / 10 / 250 KB / 90 s). The 240 s wall budget now matches the existing 4-minute inactivity watchdog. The graceful "say continue" pause still kicks in for genuinely oversized requests. **Earlier today** - Switching from `/c/:id` to `/app/:id` after `create_app` now happens as soon as the local stream finishes, instead of waiting on a slow background DB write. - Long App Builder turns that hit the per-prompt work budget no longer occasionally lose the final summary message. Terminal writes are now synchronous, and a new `final_persist_failed` reason flips the row to *failed* immediately if persistence itself errors (instead of waiting 3 minutes for the stale-reaper). **Failed executions now explain why they failed** - When an execution flips to **failed**, the system now persists a structured failure reason (e.g. `ws_inactivity_timeout`, `client_disconnected`, `openai_rate_limited`, `tool_loop_error`) plus technical details. Hovering the red status icon in the conversation list now shows a friendly message — e.g. *"Timed out — try a new conversation or lower reasoning level"* — instead of the bare *"Execution failed"*. This means post-mortems no longer depend on rotated edge-function logs. ### April 23, 2026 **App Builder now keeps a `.memory/` notebook for each app** - The App Builder maintains a small set of Markdown notes inside each app under `.memory/` (purpose, file roles, verified OData endpoints, design decisions, deferred items). The top-level `.memory/index.md` is loaded into the agent's context every turn — so follow-up questions like "what does kanban.js do?" or "where do we filter sales orders by date?" are answered from a 6 KB summary instead of re-reading the whole codebase. The folder shows up in the file tree as **Memory** at the bottom; you can inspect or edit any of the notes manually, or delete the folder entirely and the agent will rebuild it as it works. **Stuck-build recovery is now continuous (was every 15 minutes)** - A background sweeper now runs **every minute** and clears any build stuck for more than 3 minutes — including ones that were waiting on a tool confirmation. Previously this only ran every 15 minutes and ignored confirmation-pending builds. **Stuck builds now self-heal — no more 15-minute spinner lies** - If a build silently dies mid-stream (network drop, browser tab put to sleep, edge worker restart, OpenAI handshake failure), the conversation is now marked as **failed** instead of staying pinned at "Building app…" forever - The preview now shows a **Reset and try again** button after 90 seconds with no progress, so you're never stuck staring at an indefinite loader - Stale builds older than 3 minutes are auto-cleaned the next time the chat list loads or the window is refocused — old bricked conversations from before this fix will clear themselves automatically ### April 22, 2026 **App Builder — "New" button now reliably leaves the previous app** - Pressing **New** while inside an existing app no longer snaps the view back onto that app a moment later. Your next prompt now starts a clean Creator-mode conversation, and once the new app is built the URL, header and preview switch to the newly created app instead of staying stuck on the previous one - Same fix applied to the Site Builder ### April 22, 2026 **App & Site Builder — no more accidental sibling projects** - Inside an existing app or site conversation, the agent can no longer call the create-new-project tool. The tool is filtered out of the model's tool list once the conversation is bound to an `app_id` (or `site_id`) - This makes the "agent silently spawns a brand-new app while you're editing another one" mismatch structurally impossible — the URL, header, preview and conversation always stay aligned - To start a brand-new app or site, open the agent menu and pick **New** to begin a fresh conversation ### April 22, 2026 **App Builder — small apps now finish in a single turn** - The App Builder no longer stops after the first file and asks you to reply **continue** for trivial apps (a form, a calculator, a single-purpose widget). Small apps are now built end-to-end in one turn - Multi-turn pacing is reserved for genuinely large, multi-module apps where streaming the build over several turns produces a better UX and avoids response-size limits - All hard safety caps (per-file size limits, per-prompt work budget) are unchanged — only the *over-eager* "stop after one file" behaviour was relaxed ### April 22, 2026 **Platform — legacy chat execution path retired** - All chats and automations now run on the unified WebSocket execution engine. The legacy HTTP fallback path has been removed - The "WebSocket mode" toggle in **Settings → Experimental** has been removed — there is now a single, consistent execution engine for everyone - No user action required; the change is fully transparent ### April 22, 2026 **Settings — new "Fresh context on each agent run" experimental option (default ON)** - Each new message you send now starts the agent's processing loop **without** re-attaching the previous AI response. This dramatically reduces token usage and AI credit cost on long conversations, where the silent re-loading of the prior response chain was the main source of bloat - Tool-call turns *within the same run* (turn 2, 3, …) still chain efficiently — only the **first** turn of each new run is affected - You can flip the option off in **Settings → Experimental** if you want the old behaviour where the model carries a long prior reasoning chain across separate messages - **App Builder and Site Builder always start fresh on every new run**, regardless of this setting — these builders accumulate large code/page payloads, so re-attaching the prior response chain would explode token usage ### April 22, 2026 **App Builder — preview now shows live build progress instead of a frozen "Loading…" message** - Fixed an issue where, after creating a new app, the preview panel would display a static *"Loading app preview…"* message while the agent was still writing files in the background — making it look like nothing was happening when in fact the build was progressing - The preview now shows a clear in-flight state during a build: *"Building … 1m 12s · 4 tool calls"* with a live elapsed timer, so you can see at a glance that work is happening - The chat keeps showing the typing indicator and tool-use stream for the **entire** build (previously these signals could disappear partway through long builds) - The preview lights up automatically the moment the first file is written — no manual refresh needed - Empty apps opened directly now say *"This app has no files yet."* instead of the misleading loading message ### April 22, 2026 **Instance sessions — "Reconnect" prompt no longer appears when your session is actually fine** - Fixed an issue where the "Session expired" prompt could appear right after you reconnected an instance, even though valid tokens were already saved on the server. The chat now silently restores the session from the server before showing any prompt - The Reconnect prompt now **names the specific instance** whose session needs attention — for example *"Session expired for TESTDB (testdb.my.erp.net) — Reconnect TESTDB"* — so you'll never wonder which connection it's referring to when you have several - The check that decides whether to show the prompt is now strictly tied to the **active** connection in the selector, so reconnecting one instance never leaves a stale prompt up for a different one - **Apps using AI conversations:** the conversation is now bound to the **same instance you have selected in the toolbar** at the moment the app calls `operator.ai.createConversation()`. Previously, an internal database flag could occasionally point the conversation at a different instance than the one you actually had selected. The flag has been removed; the toolbar selection is now the single source of truth --- ### April 22, 2026 **App Builder — large apps now build in bounded, resumable chunks** - The App Builder now follows an **Incremental Build Protocol**: skeleton-first, then one non-trivial file per turn — so very large "build the whole app" requests no longer stall mid-generation - A per-prompt work budget (turns, file writes, bytes, wall-clock) ensures the assistant cleanly **pauses** instead of timing out when a request is too big to finish in one shot - When the build pauses, you'll see a small *"App build paused — type **continue** to keep building"* hint with a one-click **Continue** button. Picking up where it left off is just one message away - Per-file size cap (80 KB) is now enforced at the tool boundary — the assistant is forced to split oversized files into modules instead of failing silently ### April 21, 2026 **App Builder — Creator Mode no longer silently edits a different existing app** - Fixed an issue where starting a brand-new conversation in App Builder could result in the AI quietly amending one of your existing apps (whose purpose looked similar) instead of creating a new one - New conversations are now strictly bound: file tools (`write_app_file`, `patch_app_file`, `delete_app_file`, `get_app_file`, `list_app_files`) only work after `create_app` has been called in the same conversation - To edit an existing app, open it from `/apps` (or via the app selector) and continue the conversation from there **App Builder — "New" reliably leaves the current app** - Fixed an issue where pressing **New** while viewing an existing app would briefly clear the context and then snap back to the same app - **New** now consistently returns you to Creator Mode (home URL, empty preview), so the next prompt creates a fresh app - Typing in the chat while on an app's page continues to amend that app — unchanged **Reliability — App Builder no longer gets stuck after creating an app** - Fixed a class of silent hangs where the AI service would stop responding mid-conversation (most visible in App Builder right after `create_app`, before app files were written) - The connection to the AI is now monitored with a 120-second inactivity watchdog and a periodic heartbeat - If the AI goes silent or the connection drops, the request is automatically retried — and if it still fails, you now get a clear error instead of an indefinite spinner --- ### April 13, 2026 **Faster App Launching** - Opening an app now starts directly in **Execute** mode without first loading its design conversation - The related design session is loaded only when you switch to **Design**, **Code**, **Properties**, or **Deploy** - App execution now uses dedicated app routes for faster startup and cleaner app-specific URLs --- ### April 11, 2026 **App Builder — Build Custom ERP Data Apps with AI** Operator now includes a built-in App Builder — a fast, AI-assisted way to create small ERP data apps that integrate directly into the platform. Describe what you need in natural language, and the App Builder generates a working application connected to your ERP.net data via the Domain API. Built apps can be deployed in multiple ways: - **Inside Operator** — run apps directly within the Operator interface - **Full-screen** — open any app in a dedicated full-screen view - **In the ERP.net Web Client** — add apps as main menu items or embed them inside panels in other forms - **In the ERP.net Marketplace** — publish apps for other ERP.net users to discover and install Manage all your apps from the dedicated **My Apps** page — create new apps, resume design sessions, toggle visibility, or remove apps you no longer need. --- ### April 8, 2026 **Domain API Availability Check** - **Auto-discovery on connection setup** — when adding a new ERP.net instance, Operator now verifies that Domain API is activated before allowing the connection. If Domain API is missing, a clear error message explains the requirement. - **Post-authentication warning** — after completing OAuth, Operator checks Domain API availability and warns if it's not activated, so you know immediately why features won't work. - **Better Enterprise Context errors** — the Enterprise Company dialog now correctly detects when Domain API is missing (instead of showing an empty list) and advises contacting your ERP.net administrator. --- ### April 5, 2026 **More Reliable Session Recovery** - **Single-flight token refresh** — when multiple parts of the app detect an expired session simultaneously, only one refresh request is sent to the server, eliminating duplicate "invalid_grant" failures caused by token rotation races - **Reliable token persistence** — rotated tokens are now durably written to the database before the UI continues, preventing stale credentials from being used on subsequent requests - **Accurate refresh token expiry** — the system now tracks real server-provided refresh token lifetime instead of assuming a fixed 30-day window - **Precise connection identity** — the app now distinguishes between different connection types (Internal vs. Client) for the same instance, preventing session mix-ups --- --- # March 2026 Updates released in March 2026. ### March 31, 2026 **Improved Connection Management** - **Unified session status indicators** — the instance selector dropdown and the Connections management page now use the same three-state status system: **Active** (green), **Expired** (grey), and **Disconnected** (no indicator) - **Smarter session recovery** — selecting an expired connection now automatically refreshes the session using the stored credentials, instead of requiring a full reconnection cycle - **Reconnect action** — added a "Reconnect" option in the connection actions menu, allowing you to manually trigger a full token refresh when needed - **Compact connection table** — the connection type badge is now displayed inline with the instance URL, and all actions are consolidated into a single overflow menu for a cleaner layout --- ### March 18, 2026 **Agent Rename: System Expert → System Architect** - The **System Expert** agent is now called **System Architect** — emphasizing its role in architecting and designing the ERP system itself - New description: "Architects the ERP system: solves complex business problems, configures custom logic, workflows, settings, and specialized apps." - Internal key `erp_manager` remains unchanged — no impact on existing automations or saved agents --- ### March 17, 2026 **Knowledge Base** - Indexed the full help of **Retail POS Manager**, making it searchable through the Advisor agent --- ### March 15, 2026 **Calendar Management Improvements** - **Faster event creation** — calendar now retrieves available document types in a single step alongside events, eliminating the need for a separate query before creating an event **Speech Mode Improvements** - Various stability and reliability improvements to speech mode across all interaction types (Dictation, Voice → Text, Voice ⇄ Voice) --- ### March 14, 2026 **Speech Mode: Separate Dictation Mode** - **Dictation mode** is now a distinct speech mode, separate from Voice → Text. Use it as a pure drafting tool — speech is transcribed into a text buffer that you review and edit before sending. No AI execution is triggered; you stay in full control of the final message. - **Turn detection in Dictation** controls when the buffer text is sent to the chat input: choose Manual (press Send) or Pause (auto-send after silence). - The Voice → Text mode remains available for cases where you want spoken input to trigger AI responses directly. --- ### March 13, 2026 **Calendar Management Improvements** - **Improved time and timezone handling** — time fields now preserve the user's local timezone offset, with automatic fallback when the offset is missing - **Add and remove participants** — manage event attendees directly, with support for person lookup by name, email, or user ID - **Social group support** — associate calendar events with social groups on creation or update - **View event details** — new ability to fetch full event info including all participants and their record IDs **Speech Mode: Turn Detection Options** - New setting: **When should the AI respond?** — choose how the AI decides when you've finished speaking: - **Manual** — press Send or hit Enter to submit; gives full control over message timing - **Pause** — the AI responds after a configurable silence delay (0.5s to 1.4s, default 0.8s) - **Automatically (Semantic)** — uses semantic voice activity detection to intelligently determine when you've finished (Voice ⇄ Voice only) **Speech Mode: Voice Input Editing** - **Click-to-trim** — click any word in the transcript to delete it and all words after it; words highlight on hover to preview what will be removed - **Delete last word** — dedicated button next to the transcript (also available via Backspace on keyboard) - **Clear all** — X button to instantly clear the entire transcript - **Send with Enter** — press Enter on the keyboard to send the buffered transcript - **Appends to input** — dictated text is added to the chat input field instead of being sent immediately, so you can review and edit before sending --- **Save Turn Context (Experimental)** - New experimental setting: **Save turn context** — preserves tool call history between turns so follow-up messages are faster and more accurate - When enabled, previous tool calls and their results are sent as structured context to the AI, preventing it from re-fetching data or losing track of earlier results - Toggle in Settings → Experimental --- ### March 10, 2026 **File Management Capability** - New **File Management** capability for listing, retrieving, and attaching files to ERP.net objects - Manage files attached to any ERP object using the Extensible Data Object (EDO) pattern via `Systems.Core.ObjectFiles` - Organize objects hierarchically using **Folders** — create folder structures and move objects between them - Uses a gating pattern: call `get_file_management_instructions` first to unlock `list_object_files`, `get_file_from_object`, and `attach_file_to_object` - Available to Business Specialists and above --- ### March 9, 2026 **Retail POS Help Documentation** - Operator's knowledge base now includes help documentation from the **Retail POS** companion app - Users can ask questions about Retail POS features, configuration, and troubleshooting directly in chat - Search results link to the official Retail POS help pages at [retailpos.app.erp.net/help](https://retailpos.app.erp.net/help) --- ### March 6, 2026 **Speech Mode Now Available to All Users** - **Speech mode** is no longer an experimental feature — it is now available to all users from Settings → Experimental - Three interaction modes: Voice → Text, Voice → Text → Voice, and Voice ⇄ Voice (real-time conversation) - Customize language, voice (Male/Female), playback speed, and noise reduction - Speech sessions have full access to the same tools and capabilities as text-based chat --- ### March 3, 2026 **Manage Agents Capability** - New **Manage Agents** capability allows you to list, create, update, delete, and share your custom agents directly through chat - Create agents using natural language — describe the agent you need and the AI builds it for you, including name, identifier, instructions, greeting, and suggested actions - Update or refine existing agents conversationally — change instructions, base agent, reasoning level, or greeting without leaving the chat - Share agents with colleagues by email or remove shares, all through natural-text commands - Available to Power Users and above when using System Architect, Partner, or Nexus agents - Follows a discovery-first pattern: the agent lists your existing agents before making any changes **Expanded File & Image Attachments** - Chat now accepts a vastly expanded range of file types as input — including PDFs, Word, Excel, PowerPoint, CSV, code files, images, and more (50+ formats supported) - Images are analyzed at high detail for accurate visual comprehension - Maximum file size: **10 MB** per attachment **30% Reduction in AI Credit Usage** - Internal optimizations result in approximately **30% lower AI credit consumption** per conversation --- ### March 2, 2026 **Bank Sync Help Documentation** - Operator's knowledge base now includes help documentation from the **Bank Sync** companion app - Users can ask questions about Bank Sync features, configuration, and troubleshooting directly in chat - Search results link to the official Bank Sync help pages at [banksync.app.erp.net/help](https://banksync.app.erp.net/help) - Article drill-down (`get_knowledge_article_info`) now correctly supports Bank Sync articles — previously, requesting details for a Bank Sync article returned empty results --- --- # February 2026 Updates released in February 2026. ### February 28, 2026 **Faster Login for Standalone Users** - Signing in when using Operator outside an iframe is now significantly faster - The login flow now navigates directly to the authentication page instead of making an intermediate API call, eliminating CORS preflight delays --- ### February 27, 2026 **Lifecycle Callback Security Upgrade** - App installation and uninstallation callbacks from the ERP.net Marketplace now require a cryptographic signature (v2 envelope format) - Unsigned (v1) lifecycle payloads are no longer accepted ### February 26, 2026 **Knowledge Search Fix** - Fixed an issue where searching through business rules, internal cases, products, companies, and document types could return incomplete results when using date filters - All indexed items now have consistent timestamp metadata, ensuring reliable search and recency scoring **MCP Servers Integration** - Users can now define **MCP (Model Context Protocol) servers** associated with their ERP.net instances - MCP servers extend Operator's AI with external tool capabilities via the OpenAI native MCP format - Management page at `/mcp-servers` allows Power Users and Instance Admins to add, edit, and delete MCP servers - Each server can be configured with authentication (none or instance token) and optional tool filtering - **Base agent activation**: Users can activate MCP servers for built-in agents (Business Specialist, System Architect, etc.) from the Capabilities page using per-server toggles - **User-defined agent binding**: Custom agents can be bound to a specific instance and pin selected MCP servers via the new MCP Servers tab in the agent editor - MCP servers are automatically injected into AI conversations when the associated instance is connected - All MCP tool calls require explicit user approval before execution, with a confirmation dialog showing the server label and tool name - Users can auto-approve all tools (including MCP) via the "Auto-approve everything" option - [Documentation →](/help/mcp-servers) **Execution Interrupt Reliability** - Resetting an active/stalled execution now persists an **"Execution interrupted"** status message in chat history - Interrupted executions no longer save false "unexpected error" assistant messages caused by closed client streams - Final assistant persistence is skipped if the execution was reset mid-run, preventing misleading post-interrupt output **Background Execution Visual Continuity** - Switching to or reloading a running execution now restores the typing indicator and elapsed-time clock - The start time is derived from the most recent user message or conversation update for accurate timing - The "tools used" count is restored from persisted message history - When a background execution completes, the final assistant message loads automatically without requiring a manual refresh --- ### February 22, 2026 **Agent Rename: ERP Consultant → System Expert** - The **ERP Consultant** agent is now called **System Expert** - New description: "Solves complex business problems and configures the ERP: custom logic, workflows, settings, and specialized apps." - Internal key `erp_manager` remains unchanged — no impact on existing automations or saved agents --- ### February 19, 2026 **Locked Agent & Instance for Active Executions** - Once an execution has messages, the connected business instance and agent are permanently locked for that execution - The instance selector shows a lock icon and is disabled during active executions - The agent selection submenu is hidden from both the profile dropdown and the chat input "+" menu during active executions - Switching to a different instance while viewing an active execution triggers re-authentication to the correct instance - New executions continue to use whatever instance and agent are currently selected **Type-Aware Record Button Numbering** - Auto-generated "Open [Entity]" buttons now number records **per entity type** instead of globally - If only one record of a type is created, no number is shown (e.g., "Open Lead") - Multiple records of the same type are numbered starting from 1 (e.g., "Open Task 1", "Open Task 2") --- ### February 18, 2026 **Auto-Generated Record Creation Links** - When a record is created via `create_erp_record`, an "Open [Entity]" button now appears automatically — no AI credits consumed - Button labels now use singular entity names (e.g., "Open Lead" instead of "Open Leads") - When multiple records are created, buttons are numbered (e.g., "Open Lead 1", "Open Lead 2") - If the record has a DisplayText, it is appended to the label (e.g., "Open Lead — Acme Bulgaria EOOD") - The AI no longer duplicates these links in its text response - Only aggregate root entities (e.g., Sales Orders) generate buttons; child records (e.g., Sales Order Lines) do not - If more than 4 records are created in a single turn, an overflow indicator is shown - New user setting: **Record creation links** (default: ON) — toggle in Settings to control this behavior **Record Creation No Longer Requires Confirmation** - `create_erp_record` is no longer marked as a destructive tool — records are created immediately without a confirmation step **Topic Guard Setting** - New optional user setting: **Topic guard** (default: OFF) — restricts the AI to ERP.net and business-related topics only - When disabled, saves ~400 tokens per message by omitting topic enforcement from the system prompt - Toggle in Settings to enable strict topic filtering when needed **Concise Responses for Business Specialist** - The Business Specialist agent (and all user-defined agents based on it) now produces shorter, more concise text responses - Other agents (Advisor, System Architect, Sales Executive) are unaffected **Performance Optimizations** - Improved performance and reliability across chat and backend operations --- ### February 17, 2026 **Word & Excel File Attachments** - Chat now supports attaching Word (`.docx`) and Excel (`.xlsx`, `.xls`) files - Text is automatically extracted server-side and sent to the AI for analysis - Extracted content is truncated to 15,000 characters for large documents - Graceful error handling for corrupted or unreadable files **Update Data & Import/Export Improvements** - Improved performance and reliability for Update Data and Import/Export operations --- ### February 13, 2026 **Capability Rename: "Manage Records" → "Update Data"** - The "Manage Records" capability is now called **Update Data** to better complement the read-only "Query Data" capability - All user-facing labels, documentation, and agent prompts updated - No changes to internal capability keys, tool names, or automation configurations **Agent Renames** - **ERP Advisor** is now **Advisor** — knows everything about business operations and ERP.net - **ERP Manager** is now **System Expert** — solves complex business problems and configures the ERP - Updated Business Specialist description - All agent keys remain unchanged — no impact on existing automations or saved agents --- ### February 9, 2026 **Follow-Up Execution Continuity** - Automations configured with "Continue in same execution" now reuse the existing execution when a follow-up event arrives in the same thread (e.g., email replies) - Action buttons are automatically disabled for automation executions — no wasted tokens on interactive UI elements in headless runs - If the execution is busy, the follow-up is queued as a **Waiting** run and automatically processed when the current run completes - New `thread_id` tracking on executions enables thread-based lookup - Run history now displays the **Waiting** status for queued follow-up runs **Automation Capabilities Merged with Agent** - Automation-configured capabilities are now **merged** (unioned) with the user-defined agent's capabilities instead of being restricted to their intersection - This fixes an issue where capabilities like Email, explicitly enabled on an automation, were stripped if the assigned agent didn't include them - Interactive chat sessions continue to respect the agent's configured capability subset ### February 8, 2026 **Automations Menu Simplified** - The Automations submenu has been replaced with a single direct menu item navigating to `/automations` - Monitor and Event Sources sub-items removed (now integrated into the Automations page) - Automations remain restricted to **Power User+** (level 30+) **Automation Deletion Fix** - Dropping the `execution_type_integrity` constraint allows automation deletion to proceed without errors **Event Skip Reasons** - Events that are skipped (no matching automations) now store a clear reason in the `message` field - The Events dashboard shows skip reasons with an info-style banner, distinct from error messages - The `error_message` column has been renamed to `message` to support both error and informational context **Auto-Approve Capabilities for Automations** - Automations now support **per-capability auto-approve** for destructive tools, configurable from the Capabilities tab in the automation editor - In Custom mode, each destructive capability shows a shield icon toggle — amber when auto-approve is active - "Auto-approve all" button sets global auto-approval for the automation's executions - Auto-approve settings are persisted on the automation and passed to every execution **Real-time Mail Notifications** - Mail event sources with emission mode set to **Real-time** now receive instant push notifications via Microsoft Graph change notifications (MS365) or Gmail Pub/Sub watches - Push subscriptions are created automatically when switching to Real-time mode and torn down when switching away - **Automatic subscription renewal**: Expiring subscriptions are renewed nightly — MS365 (~3 days) and Gmail (~7 days) subscriptions are refreshed before they expire with no manual intervention required - The sync mechanism acts as a catch-up fallback for real-time sources, ensuring no emails are missed - Subscription metadata is stored polymorphically on the event source, ready for future instant-message platform support - Sources with emission mode **Never** are now skipped during scheduled sync runs **Event Source Emission Mode** - Mail event sources now support an **emission mode** setting: Real-time, On sync only, or Never - Configured during the post-OAuth mailbox selection dialog when connecting a mailbox - Emission mode is displayed as a badge on the Event Sources page and in the automation editor's trigger picker - Default is "On sync only" for backward compatibility with existing sources **Business Context Persistence per Execution** - Each execution now snapshots the active business connection and enterprise context (company + location) at creation time - When switching between executions, the header bar automatically reflects the business context that was active when the execution was started - The AI agent always sees the correct business context matching the header display - When no execution is active, the header manages the global default for new executions **Reasoning Level Persistence per Execution** - Each execution now snapshots the active reasoning level (Fast/Smart/Expert/Genius) at creation time - When switching between executions, the reasoning badge reflects the level that was active for that execution - Changing the reasoning level while an execution is active updates the execution's persisted level - When no execution is active, the reasoning badge manages the global default for new executions ### February 8, 2026 **Capability-Scoped Auto-Approve for Destructive Tools** - Auto-approve for destructive tool confirmations is now **per-capability** and **persisted** on the execution - When a destructive tool asks for confirmation, you can now: - **Execute** — approve this single action - **Auto-approve [Capability]** — automatically approve future actions under that capability (e.g., "Auto-approve Email") - **Auto-approve everything** — (overflow menu) approve all destructive actions for this execution - Auto-approve settings survive page refresh and execution switching - New status messages distinguish between single approval, capability-level, and full auto-approval - **Manage auto-approve from the Capabilities dialog**: Open the `+` menu → Capabilities to see shield icons next to each destructive-capable capability, allowing you to toggle auto-approval proactively without waiting for a tool to trigger ### February 8, 2026 **Database Rename: `conversations` → `agent_executions`** - The `conversations` table has been renamed to `agent_executions` to better reflect its purpose as agent work execution records - Column `conversation_type` renamed to `execution_type` - All constraints, indexes, triggers, RLS policies, and database functions updated accordingly - Frontend hooks and components updated with backward-compatible aliases - No user-facing URL changes — `/c/:id` routes remain the same **Email Folder Management** - New `list_mail_folders` tool to list all folders/labels in a connected mailbox - New `move_email_to_folder` tool to move emails to specific folders by folder ID - New `list_folder_emails` tool to list emails in any folder by ID (unlike `list_emails` which only supports predefined folders) - Supports both MS365 and Gmail providers --- ### February 7, 2026 **Visual Event Filter Builder** - New visual filter builder in the automation editor's **Filter** tab replaces raw JSON editing - Field selection uses a dropdown populated from the event type's schema - Type-aware value inputs: date picker for date-time fields, boolean toggle, and text input - Support for nested AND/OR groups for complex filter logic - 11 operators available: equals, not equals, contains, does not contain, starts with, does not start with, ends with, does not end with, matches regex, does not match regex, and exists - Regex operators enable powerful domain-based email filtering (e.g., exclude emails from `@internal.com`) **Schedules as Event Sources** - Schedules are now managed as event sources alongside mailboxes and webhooks - Create reusable schedules from the Trigger tab or the Event Sources page - Multiple automations can share the same schedule - The automation editor no longer has a separate Schedule/Event toggle — all triggers use the unified Event Source picker - Backend scheduler queries the new `schedules` table and supports legacy inline schedules during transition **Event Sources** - New unified Event Sources page to manage all connections that emit events (mailboxes, schedules, webhooks, ERP connectors) - Each mail connection now automatically creates an event source with linked event types - Deleting an event source removes the entire hierarchy (including the underlying mail connection) - Automation editor now uses a two-level event picker: first select the event source, then the event type - Replaces the previous flat event type dropdown for clearer, source-aware event selection **Capabilities Page: Default vs. Custom Mode** - New two-option mode selector on the Capabilities page: **Agent defaults** (all included capabilities active, recommended) or **Custom** (manually toggle individual capabilities) - Agent defaults mode hides toggle switches for a cleaner read-only view - Replaces the previous preset dropdown with a more intuitive experience --- ### February 4, 2026 **Agent Editor Improvements** - Suggested actions now derive from agent greeting buttons—no separate configuration needed - Added expand button (↗) to Suggested Actions editor for editing long messages or URLs in a larger modal - Consolidated Suggested Actions editing into the Greeting tab for a streamlined workflow - Improved macro editing with larger dialogs and quick search **Stability** - AI engine errors are now automatically retried with exponential backoff for better reliability --- ### February 3, 2026 **Agent Sharing** - Share user-defined agents with other users via the Sharing tab - Shared agents appear in recipients' agent selection under "Shared with Me" - Recipients can use shared agents but cannot modify their definitions **Import/Export Data** - New capability for bulk import and export of ERP.net data using the standard Import format - Supports create, update, delete, merge, and find operations with transaction control **Tool Gating** - Complex tools now require reading documentation first before becoming available - Prevents malformed requests by ensuring proper understanding of tool requirements --- ### February 2, 2026 **Execution URLs** - Each execution now has its own URL (`/c/:id`) for bookmarking and sharing - Browser back/forward navigation works between executions - Legacy `?conversation=` query param auto-redirects to new format **Draft Action Buttons** - New "draft" button type that populates the input field without sending, allowing users to review and edit before submitting - Useful for complex queries, templates with placeholders, or suggestions users might want to customize - Draft buttons display with a dashed border and pencil icon for visual distinction --- --- # January 2026 Updates released in January 2026. ### January 31, 2026 **Settings Enhancements** - Added "Action Buttons" toggle in Settings - allows users to enable/disable interactive quick-action buttons - Both "Execution details" and "Action Buttons" now show credit usage information - Action buttons now only appear after messages are fully streamed **Documentation** - Added Settings documentation page covering Execution Details and Action Buttons features - Introduced Release Notes page (this page!)