Build an application from a plain-English description and the data you already use in Knowi. For example, create a sales review with filters and order details, a customer portal, or an operations app for tracking tasks and approvals. Each App can have its own pages, navigation, branding, and actions. Knowi generates the code and handles building and hosting it.
The flow is Describe → Build → Preview → Publish. You can describe changes whenever you need them. Each generated version is saved, and you choose which version goes live.
We recommend building through MCP:
- Build through MCP (recommended): use a connected AI assistant to find your data, create an App, refine it, preview it, and publish it through a conversation.
- Build in Knowi: use the Apps page if you prefer to enter prompts and review previews directly in Knowi.
You can build through either path using prompts. If you need to edit the source yourself or connect an App to another system, see Code & integrations.
Before you begin
Knowi Apps must be enabled for your account, along with AI Agents access. Contact your Knowi account representative if Apps is unavailable, or select Request access on the Apps page. Your Knowi administrator assigns permission to create and edit Apps; publishing requires a separate permission.
The walkthrough builds a Sales Review App using sales data you can access in Knowi. Start by asking the assistant to find a suitable dataset and check its fields, using the prompt below. For a different use case, describe the data and App you need.
Choose who can open the App. For this internal sales review, use Knowi sign-in required so viewers sign in with their Knowi accounts and see only data they are allowed to access. If that option is disabled, ask your administrator or Knowi Support to enable sign-in for Apps before publishing. See Access and security for the available options and form defaults.
Build through MCP (recommended)
MCP (Model Context Protocol) connects your AI assistant to Knowi so it can perform the same App operations through tools. You describe the result you want; the assistant uses Knowi's knowi_app tool to create and update the App. You can also open that App in Knowi to review its versions and settings.
Connect and check setup
Follow the MCP Server connection guide for your client and Knowi deployment, then sign in with your Knowi account. The guide links to client-specific setup instructions. Connecting does not grant extra App or dataset permissions.
In your connected assistant, start with:
Use Knowi's knowi_app tool to check whether I can create an app. Show any missing setup and whether Knowi sign-in is available.
The assistant calls setup, which checks the available repositories and configuration. If Knowi-managed repository creation is available to you, the assistant can create one as part of creating the App. Otherwise, a Knowi administrator needs to make a writable repository available. You can choose an existing repository by the label returned by setup.
Describe and generate
First, ask the assistant to find data for the App:
Find Knowi datasets I can access that would work for a sales review App. Suggest a dataset and check which fields contain order dates, regions, and revenue. Ask me to confirm the dataset before building.
Review the suggestion and confirm the dataset. If the data does not support part of the example, ask the assistant to adjust the App to the available fields. Then ask it to build:
Create a Knowi App named Sales Review with an available slug based on sales-review-team, using the dataset and fields we just agreed on. Use a new Knowi-managed repository if setup allows it; otherwise show me the available repositories. Require Knowi sign-in and use no database. Show total revenue, revenue by region, and an orders table, with date-range and region filters where the data supports them. Make it work on desktop and mobile. Generate a preview for me to review. Do not publish yet.
The assistant creates the App shell, reads its current source, and writes the code itself. The tool sequence is setup → create → read → change → status → preview. The assistant declares the selected data in app.json, submits its files through change, then checks status until the build is Ready or reports a failure. MCP does not invoke Knowi's AI generator.
Once the build is Ready, the assistant calls preview with that version's ID because you requested a preview. It returns a short-lived link to review the App. Checking status alone never starts a preview. If you return later, ask:
Check the status of my Sales Review App and give me a fresh preview link for the latest Ready version.
Refine and publish
After inspecting the preview, ask for a change:
In my Sales Review Knowi App, add a monthly revenue trend above the orders table. Keep the existing filters and dataset. Generate the change and send me its preview.
The assistant reads the latest source, submits change, checks status, and calls preview for the Ready version you requested. When you are satisfied, make the publishing request explicit:
Publish the Sales Review version I just reviewed. Confirm its version number and live URL.
The assistant publishes that Ready version using its returned versionId and an explicit confirmation. A request to create or refine the App alone does not publish it. See Publish and share for who can open the URL.
If you changed source directly in Git, ask the assistant to build the latest repository commit and show its preview. The build action compiles existing source; change commits code written by your assistant and queues its build. The MCP action reference lists the fields and permissions for each action.
Build in Knowi
You can also build from the Apps page in Knowi. For this sales review example, select a dataset you can access that contains sales dates, regions, and revenue. Adjust the prompt to fit your data.
Create your first App
- Select Apps in the left sidebar, then New app.
- Enter Sales Review as the App name. Choose an available URL slug, such as sales-review-team. The slug becomes part of the live address.
- Select your sales dataset under Data, above the description field. Each pick is listed with a Remove link. When editing an existing App, its data, write actions, and brand assets appear in the right-side App resources panel.
-
Enter this description, adjusting the dataset and field names to match yours:
Build a sales review app for regional managers using my selected sales dataset. Show total revenue, revenue by region, and a table of orders. Add date-range and region filters that update all three. Use a clear layout that works on desktop and mobile. Require Knowi sign-in.
-
Expand Advanced settings > Repository. For the simplest setup, choose Knowi-managed, enter a repository name, and select Create repository. This is where Knowi saves the generated code; you do not need to use Git commands. If you cannot create a repository, ask your Knowi administrator to make one available, then select it. Existing repository options are covered in Choose where the source lives.
- Under Access, confirm Knowi sign-in required. Leave Database as No database for this example, which only reads Knowi data.
- Select Build app.
Knowi writes the source, saves a version, and builds it. Progress appears in the Builder. Generation usually takes 5-10 minutes; complex Apps may take up to 15 minutes. You can leave the page and return later, or select Request cancellation while generation is running. If a setting is missing, Knowi names it and opens that setting.
While the first build is running, its selected data stays visible and cannot be edited. If generation fails or is cancelled before a version is created, reopen its conversation to recover the original request and selected data. Successfully uploaded images remain available for retry. Recovery does not replace text or data selections you have already changed.
Review and refine
Use the left navigation to move between five sections. On smaller screens, use the App view selector:
| Section | What it contains |
|---|---|
| Builder | Your private conversation and its build results, with a separate App resources panel for data, write actions, and brand assets. |
| App settings | URL and domain, access, repository, storage, embedding, and secrets. |
| Preview | Starts the selected Ready version when you select this section. The version list in the preview toolbar switches to any other Ready version. Includes publishing controls. |
| Commits | Repository commits from Knowi, assistants, and Git, plus a Versions view of builds, their builders, and publication details. |
| App activity | Recorded usage and Knowi sign-ins across the App, with date and event filters. |
Each person has one private Builder chat per App, and it opens where you left off. Unsent text stays in the composer while the App is open; it is not saved for reopening later. Your requests stay private: each build's shared commit message is a one-line summary of what changed, written by the AI. Commits brings together shared changes from Knowi, Claude, Codex, other MCP clients, and Git; external chat transcripts are not imported.
App resources lists what the App's builds use. A change saves as soon as you make it, and every build uses the current list, so a dataset you add stays added even if you leave before building. Items without a label are already in the latest built version. The others are labeled:
| Label | Meaning |
|---|---|
| Not built yet | Added since the latest build; the next build picks it up. |
| Removed | Removed from the list; the latest build still uses it until you build again. Select Undo to restore it. |
| Off | A write action that is turned off. |
Data lists datasets and dashboards; AI appears there once the App's code calls it. Write actions lists each saved action with the values the form sends and the values that come from the signed-in user. Brand assets lists uploaded images. When anything is not built yet, the panel counts the changes, and the next Build changes adds a list of them to your request. With nothing typed, Build changes builds just those changes. One-use Design references stay with the composer.
If an assistant or a Git push builds a version whose data differs from your saved list, that version's data becomes the list. Assets added through an assistant or Git are part of the source and do not appear in the brand asset list. See Attach design references and brand assets for persistence and removal.
Commits opens on the commit list: the Git author, commit message, identifier, and date, including commits made outside Knowi. Select Versions for one row per version with its commit subject, build state, and builder; expand a row for build and publication details. Ready versions have Preview and permission-gated Publish actions. Commits Knowi makes name the signed-in person who asked for the change as the Git author, with Knowi Apps as the committer, for example jay@knowi.com via Knowi Apps. Where recorded, Requested by identifies the authenticated person who submitted the change, separately from the Git author. Publication details identify the publisher, and the client is shown when recorded. Older records show names only when their saved identities can be resolved.
Version details also show shared Agent-provided notes when an MCP assistant supplied a change summary or handoff. Notes attached to an earlier version are labeled accordingly. These notes help another assistant continue the work; they are separate from your private Builder conversation.
Use Search history to find messages, commit identifiers, people, or tools such as Claude and Codex in the loaded records for the selected view. Load older records to search more history; if the Commits view reaches its limit, open the repository for earlier commits. Refresh also reloads app versions and the published version so changes made through MCP become available for preview and publication without reopening the App. Your unsent request, selected data, and running preview remain in place.
Build progress appears beside your request in Builder. It shows the steps reported by the build service when available, or the current queued/generating state. Each successful build has a result card with its version and Ready/Live status. Its Preview and, with publish permission, Publish actions target that exact version. On a wide screen, Preview opens the running App beside your chat, using about two thirds of the screen; Close preview returns to the full Builder. You can also select the Preview section to run the selected Ready version, or Preview beside a Ready version in Commits > Versions. Opening the App in Builder or completing a build does not start a preview. For the Sales Review example, check that the totals match your data, the date and region filters update the charts and table, and the layout works at the sizes your viewers will use. The generated design can vary; the prompt describes the behavior to check.
To refine it, return to Builder, enter a request in Ask for a change, then select Build changes:
Keep the existing sales review. Add a monthly revenue trend above the orders table, and show which date range and region are selected.
Review the new version when it is Ready. Each successful change creates another saved version. Use Commits > Versions to review an earlier version. Selecting a different Ready build starts that version's preview; returning to an already running preview reuses it. Build changes starts from the latest Ready version, even when you are reviewing an earlier one. Full screen gives you more room to inspect the preview.
Once you have reviewed the result and its access settings, follow Publish and share. Preview has some intentional differences from the live App, described below.
Preview versus live
Preview lets you review a version before publishing it. Select Preview, or explicitly request the MCP preview action for a Ready version. Opening a preview never replaces the live version. If it expires or cannot load, select Retry preview to start it again, or request a fresh link through MCP.
| What you are checking | In preview | In the live App |
|---|---|---|
| Dataset results | A Knowi sign-in App uses the previewing editor's current data permissions. Public and App-managed Apps use their anonymous data boundary. | A Knowi sign-in App uses each viewer's permissions. Public and App-managed Apps use the explicit App-level dataset grant. |
| AI text inside the App | The AI capability returns a dry-run result without calling the provider. This is separate from the AI that builds your App. | Authorized requests call the configured AI provider. |
| Email and report schedules | The report actions do not send mail or save schedules. | Authorized actions send or schedule the report. |
| Saved workflow data and integrations | Preview does not use the live managed database or App secrets. Governed state writes and HTTP calls return dry-run results. | Configured storage, secrets, and permitted integration actions are available. |
| Write actions | A saved write action returns dryRun: true and does not touch the destination database. |
Signed-in users with App access can run its saved actions against the destination database. |
Check these live-only behaviors after publishing with the appropriate test data and recipients. View as user opens the published version and is useful for checking another user's data access; its read-only restrictions prevent testing write actions.
Publish and share
- Review the selected Ready version and confirm its App settings > Access mode.
- Return to Preview, select Publish vN for the version you want live, and confirm. Publishing requires a separate permission from editing; you can also publish from a Ready build result in Builder or the Versions view in Commits. Through MCP, explicitly ask the assistant to publish the version you reviewed.
- Wait for Live, then select Open live in the header. Knowi provides an address such as
https://sales-review-team.apps.knowi.com. - For a Knowi sign-in App, share the App with the intended users or groups and confirm they can access the selected data. Then send them the live URL.
Publishing checks the release before sending live traffic to it. If the build or publication fails, the previous working version stays live. Editing the prompt, generating another version, or pushing source to Git does not by itself replace the live App.
When the selected version is already live, its Publish button is hidden. To refresh the live runtime or apply changed secrets without releasing a different version, open App settings > App actions and select Republish live version. This requires publish permission and always targets the published version, even if you are reviewing or previewing another one.
Some settings apply immediately. Saving a live App's access mode takes effect without publishing again. Review access changes before saving them; they are separate from reviewing a new source version.
Share an App
In the Apps list, open the row's ... menu and select Share. Sharing has two effects:
- Inside Knowi, it lets recipients find the App. Full access lets them edit it, subject to their own App permissions. Lower access levels are view-only. Publishing and sharing also require the relevant permissions.
- On a live Knowi sign-in App, it grants App access to the selected users or groups. They must also have permission to the data they need. Sharing the App does not automatically share its datasets or dashboards.
Public Apps are available to anyone with their URL. App-managed Apps apply their own login rules. Knowi's Share dialog does not restrict those visitors.
New Apps are shared with the creator's auto-share groups, if configured. In Knowi's Apps list, users see Apps they own or that are shared with them, including administrators. A live Knowi sign-in App also permits account administrators.
Show an App in the Knowi menu
A live App can appear in the Knowi left menu, so people reach it without a separate URL. Open App settings > Knowi menu, select Show this App in the Knowi menu, and save. This requires publish permission and write access to the App, and the App must be live. The change applies on the next page load.
The entry opens the App inside Knowi, signed in as the viewer. Who sees the entry follows the App's access mode:
- Knowi sign-in required: the users and groups the App is shared with, and account administrators. Share the App first, and make sure those people also have access to the data it uses; the menu entry does not grant data access.
- Public: everyone in your account.
- App manages access: not available, because Knowi cannot sign its viewers in.
Under Menu icon, pick the icon the entry uses: analytics, task and approval icons, and icons for common lines of business such as finance, health care, logistics, hospitality and customer support. All are line icons in your theme's menu colours, like the built-in entries. Menu entries are listed by App name. Up to three Apps appear as their own menu entries; more than three collapse into one Apps entry that lists them. Turning the setting off, unpublishing the App, or switching it to App manages access removes the entry.
Update or roll back
Build and preview a change, then publish the new Ready version when approved. To undo a release, select Preview beside an earlier Ready version in Commits > Versions, then select Publish vN in Preview. The confirmation identifies this as a rollback and names the version. Rollback changes the code without rebuilding it; it does not roll back saved App data.
The version states are:
| State | Meaning |
|---|---|
| Queued or Building | Knowi is preparing the selected version. Wait for it to finish. |
| Ready | The build can be previewed or published. A Ready build is not live until you publish it. |
| Failed | The candidate could not build or start. Read its error; the live App remains unchanged. |
| Live | This version serves the live URL. |
A live App continues running if its Git host is unavailable. The connection must be restored before you can generate or build another version.
Access and security
On a new App, choose the mode under Advanced settings > Access. On an existing App, use App settings > Access; changing it requires publish permission and applies to live traffic as soon as you save.
| Mode | Who can open the live App? | Whose data permissions apply? |
|---|---|---|
| Knowi sign-in required | Signed-in Knowi users in the App's account with App access, including the owner, users it is shared with, and account administrators. | Each viewer's Knowi asset permissions and row-level restrictions. |
| Public | Anyone with the URL. | Selected datasets use an App-level grant checked against the publisher's current dataset access and content filters. Individual visitor permissions do not apply. |
| App manages access | Visitors allowed by the App's own authentication system. | Those visitors have no Knowi identity. Selected datasets use the same App-level grant as Public Apps. |
The New app form selects Knowi sign-in required when sign-in for Apps is configured in your Knowi environment. If it has not been configured, that option is disabled and the form selects Public instead. Public means anyone with the published URL can open the App without signing in. Check the Access setting before publishing. For an internal App that requires Knowi accounts, ask your administrator or Knowi Support to enable App sign-in first.
For a Public or App-managed App, treat the selected dataset as data the App may expose to every visitor allowed by its access mode. Private dashboards and identity-required actions still require Knowi sign-in. Selecting App manages access does not create a login system; the App must implement and configure one.
Apps are isolated from other Apps and accounts. App code does not receive your Knowi browser session or datasource credentials. Use the App's Secrets settings for third-party API keys; never put them in prompts or source code. See using secrets in App code.
Improve and manage your App
The Apps page lists each App's creator, access mode, status, live URL, and last update. Search by name or URL slug, or filter to All, Live, or Drafts. Open a row's ... menu to edit, share, view as another user, or delete, depending on your permissions.
Attach design references and brand assets
Use Design reference in the composer or + Upload under Brand assets in the App resources panel. Dragging an image onto the composer adds a design reference:
- Design reference: a screenshot, mockup, or style sample to guide the next generation only. Accepts PNG, JPEG, or WebP up to 4 MB. It does not become part of the App's source.
- Brand asset: a logo or image the App should display. Accepts PNG, JPEG, WebP, or SVG up to 1 MB. It is saved with the App's source so later versions can keep using it.
For example, attach a logo as a brand asset and request: "Use the attached logo in the header and use its colors for the buttons." You can use up to four of each kind per generation, totaling 8 MB.
On an existing App, successfully uploaded images waiting for a build remain available after you reopen it. A failed or cancelled generation keeps its unused attachments for retry. After a successful generation, design references leave the composer and brand assets show In the app. Brand assets already saved in the source can be reused without attaching them again.
Remove an unused attachment with its Remove button before building. Removing a pending upload does not remove a file already saved in the source. A brand asset marked In the app is a record of an earlier upload, not a file you can delete here; request a source change to remove or replace an image used by the App. If an upload fails, attach the image again after correcting the reported problem.
To replace a logo, attach the replacement as a brand asset and name it in your change request. For a branded Knowi sign-in page, use a logo no larger than 64 KB. See image limits for file validation and naming details.
Sign-in branding
For a Knowi sign-in App, ask the builder to use your App's name, logo, and colors on the sign-in and MFA pages. For example: "Use my attached logo and the App's blue buttons on the sign-in page too." Review the build and publish the updated version to apply the branding. Developers can edit the branding declaration directly.
Settings
Open App settings in the left navigation of an existing App, or use App view on smaller screens. On the New app screen, setup options remain under Advanced settings below the prompt. Expand a row to see its options. Some settings appear only after the App exists or when your permissions allow them.
Use the pencil beside the App's name to rename it. The App actions section lets you republish its live version, open scheduled reports, or remove the App, subject to your permissions. Open live and View as remain in the App header.
| Setting | When to use it |
|---|---|
| URL & domain | Change the URL slug before first publication, or attach a custom domain. |
| Access | Choose who can open the App. Changes to a live App apply immediately. |
| Repository | Choose or create the source repository for a new App. On an existing App, inspect its repository, branch, commit, and release state, or select Build after source changes. |
| Database | Add managed storage when the App needs to save its own records, such as notes, tasks, or approvals. |
| Embedding | Allow selected websites to display a published App in their pages. |
| Knowi menu | Show the live App in the Knowi left menu, where it opens inside Knowi for the people who can use it. See Show an App in the Knowi menu. |
| Secrets | Save third-party API keys the App's server needs. Publish again to apply secret changes. |
| Write actions | Lists the App's saved actions and opens them in the Builder's App resources panel, where you add and edit them. See Write actions. |
Saving settings does not rewrite the App's source. After changing access, storage, selected Knowi assets, or attached images, select Build changes with an empty prompt to let Knowi write the change description, or describe the change yourself. A name change alone still needs a prompt.
Renaming changes the display name. The URL slug can change until first publication, after which it is locked. Changing an unpublished slug changes its URL and breaks links to the old address. For a different live address, use a custom domain.
Deleting an App requires typing its slug and takes it offline immediately. Its versions and history are retained for administrator recovery. Source history remains in Git; a Knowi-managed repository is archived when no App uses it.
Optional managed App storage
Keep No database when the App only reads Knowi data. Choose Managed PostgreSQL when it needs to save its own records, such as tasks, approvals, preferences, or action history.
For a new App, choose storage under Advanced settings > Database; Knowi provisions it during generation. On an existing App, open App settings > Database, select Managed PostgreSQL, then Provision Database. To revoke storage, select No database, then Save. The row shows status and the applied schema version.
Where backups are enabled, a nightly backup is taken automatically. Select Back up now on a Ready database to create one yourself. Knowi also takes a backup before revoking storage or removing the App, and stops the operation if that backup fails.
Where restore is enabled, select Restore beside a backup. It replaces the current database, so Knowi first backs up the current data. Restore is available only while the App has no published version. If it fails after replacing data, keep the App unpublished and contact Knowi Support or restore the backup taken just before the operation.
Revoking storage removes runtime access without immediately deleting data. The panel shows its scheduled deletion date, 30 days by default unless your operator sets a different period. Back up or provision again before that date. Preview does not use the live managed database; publishing and rolling back code do not erase saved records.
Write actions
A write action lets an App change a record in your own SQL Server database, for example approve an order or close a ticket. An administrator saves the SQL once in Knowi; the App supplies values and Knowi runs the statement with the connection's stored credentials. App users never choose a database, see the SQL, or receive a password.
Write actions require a Knowi sign-in App and DBWrite enabled for the account. Contact your account manager to enable DBWrite.
Actions inherit App access. Any signed-in user who can open the App can run its enabled actions, including deletes. Manage access through the App's existing sharing settings. There is no separate action audience. Creating or changing actions still requires App editing and datasource permissions. Saved SQL and trusted user values restrict which records each action can affect.
Set one up in three steps:
- A datasource administrator edits the SQL Server connection and checks Writable Destination. Only SQL Server connections are supported today. See SQL Server.
- In the Builder's App resources panel, select + New under Write actions. Name the action, choose the database, and enter the SQL, writing each value as
$c9_name$. Knowi lists the values as you type and shows where each comes from. Set each value's type and select Save. Saving validates the statement; it does not run it. - Ask the Builder to add a button that runs it, for example "Add a button that runs the write action approve-order, sending status and orderId." Build, preview, and publish as usual.
| Field | What to enter |
|---|---|
| Name the app uses | A stable name the App code uses, such as approve-order: up to 64 letters, numbers, periods, underscores, and hyphens. It cannot change after saving. |
| Database | A SQL Server connection in your account with Writable Destination checked that you may edit. |
| SQL | One INSERT ... VALUES, UPDATE ... WHERE, or DELETE FROM ... WHERE. Write each value as $c9_orderId$, without quotes; the older :orderId spelling still works. Exactly one target row must change. Common table expressions, OUTPUT, and linked-server functions are rejected. Deletes target one table; joined and multi-table deletes are not supported. |
| Values | The name decides where a value comes from, when you save. $c9_user_id$, $c9_user_username$, $c9_user_name$, $c9_user_timeZone$, and any name used as a field in the account's customer, group, or user filters come from the signed-in user: the App cannot send or change them, a filter must give the person one enabled Equals value, and a missing or ambiguous one blocks the action. Every other name comes from the form. To have the form send a value whose name matches a filter field, give it another name. Choose each value's type (text, integer, number, or boolean); for a form value, open Rules to make it optional or limit it with allowed values (a comma-separated list, or a JSON list when a value contains a comma), a minimum and maximum, or a longest text length. |
| On | Turn it off to block new runs without deleting the action. |
Saving an action changes the live App at once. When you add a form value, the editor says so: build and publish so the App sends it. Delete removes the action; buttons that use it stop working right away. Where a value comes from is decided when you save, so a filter field added to the account later applies to an action after it is saved again.
Opening an action saved with :name values, or with a user ID, username, or differently named filter field as a source, rewrites it to $c9_name$ values for you to review and save. Until you save, it keeps running as saved.
Tokens bind values safely; they do not insert SQL text. Do not quote a token or use it as a table or column name. Macro defaults, lists, formatting, date expansions, and optional SQL fragments are not supported.
Example, approve-order:
UPDATE dbo.customer_orders SET status = $c9_status$, version = version + 1 WHERE id = $c9_orderId$ AND tenant_id = $c9_tenant_id$ AND version = $c9_expectedVersion$
Here the App sends orderId, status, and expectedVersion, with status limited to the allowed values approved, rejected. Because the account's filters use tenant_id, that value comes from the signed-in user's or group's tenant_id filter; it never falls back to App input. The user can then change only rows in their own tenant. The version test keeps one person from overwriting another's concurrent edit: when the row changed first, the action returns a conflict and the App should reload the record.
To delete a record, save a separate action such as delete-order:
DELETE FROM dbo.customer_orders WHERE id = $c9_orderId$ AND tenant_id = $c9_tenant_id$ AND version = $c9_expectedVersion$
Use the same value types; tenant_id again comes from Knowi. Ask the builder to show a confirmation before calling the delete action. If records need to be recoverable, use an UPDATE that marks them deleted instead. Delete actions use the same access checks, preview behavior, and write activity records as other actions. The row limit counts rows directly affected by the statement; database triggers and cascading foreign keys can affect related records.
Each run uses one database transaction. One changed row commits. Zero rows is reported as a conflict, and more than one row is rolled back and reported as failed, so a statement with a weak WHERE cannot change a whole table. Knowi checks the user's current App access, the saved SQL, and the destination's Writable Destination flag on every run. Unchecking Writable Destination blocks new runs from every App; it cannot undo a committed write.
The database login needs only the privileges those statements require. Use a dedicated login limited to the tables the actions touch.
Review write activity
Open App activity to inspect tracked usage across the App. Filter to write events to review the action, outcome, user, time, request ID, and rows affected. These knowi.write records use the dataset's normal access permissions and can also power dashboards, reports, and alerts (see App activity and custom events).
Knowi's account event log records every run as App Action Execute and each saved, changed, or removed action as App Action Configuration. Both carry identifiers only, never the SQL, input values, or record contents. Like other App events, these records are written in the background and can be lost during overload or failures.
Reports from an App
An App sends and schedules reports for its own pages. Ask the builder for an Email this report or Schedule delivery button, and its server calls the report.send or report.schedule capability while handling the viewer's request. Core supplies delivery and the scheduler, so a schedule keeps running without the App page open. See runtime report actions for developers.
Those reports show up in Reports with the owner's other scheduled reports, marked with an App chip. Open an App, then App settings > App actions > Scheduled reports to filter that list to one App. Recipients, delivery actions and the schedule stay editable there, and a report can be paused, resumed or deleted. Only the App can change which page it attaches.
Live calls require a Knowi sign-in App and a viewer with permission to create reports, send reports by email, and view the App. Pages render with that user's current permissions and content filters, from the published version at execution time. Public and App-managed Apps have no Knowi viewer identity, so they cannot send reports.
Embed an App in your site
A published App can appear inside your portal. Open App settings > Embedding, enable Allow this app to be embedded, list the allowed sites, and save. This requires edit and publish permission. Only the listed sites can frame the App.
Use Copy to get the integration snippet. A Public App uses an iframe; a Knowi sign-in App needs your portal's developer to supply a Knowi single sign-on token for each viewer. App-managed Apps cannot be embedded. Embedding does not grant access to the App or its data.
Publish the App if it is not live yet. On a live App, embedding settings apply when saved. If the panel reports an older runtime, select Republish to update it. Some browsers block sign-in inside a frame on another site; using an App custom domain under your portal's domain avoids that issue. A Knowi dashboard inside an App does not display when the App is itself embedded.
See embedding setup and code for site rules, tokens, and browser behavior.
View app as a user
In the App editor, select View as… in the App header, or View as user… in the App's ... menu on the Apps list. View as always opens the live, published version of the App, not the version you are previewing; its tooltip and dialog name that version, for example v10. The button stays in the toolbar whichever version you preview. Until the App is live and uses Knowi sign-in, the button is disabled and its tooltip gives the reason. Account admins, Knowi support admins, and users with user:login-as can use it. Knowi checks both your access to the App and the same login-as permissions used elsewhere in Knowi.
The dialog lists:
- You: choose Open as yourself to sign into the published App as yourself, with full access and no password prompt.
- Has access: the App's owner, users it is shared with directly or through a group, and account admins.
- No access to this app: open one to confirm that the App shows its access-denied page.
Search by name or email to find other users. Select a user and choose Open as [name].
The App opens in a new tab without a second login or MFA prompt. When viewing as another user, a banner identifies that user, and data queries use their permissions and content filters. The session is read-only: saving App state, sending or scheduling reports, and outbound requests other than GET and HEAD are refused, and custom events are not recorded. Exit clears that App session and returns to Knowi's Apps page. After 30 minutes, the View as session ends and the login page appears. Signing into an App while using Knowi's login-as feature gives the same read-only session and banner.
A View as session starts only from this dialog. Knowi issues a short-lived confirmation for the user you select, so a link to the App cannot open it as someone else.
Your Knowi tab keeps its current identity. App sessions are cookies scoped to the app's origin, so other open tabs on that same app domain share the selected user's app session.
An App Login As audit entry records the app, selected user, and original operator. Account-admin entries appear in the customer's audit log. Knowi support entries belong to the support operator's own account. Page views and custom app events from impersonated sessions are excluded from app usage analytics.
App activity and custom events
Published Apps record page views, request errors, and usage of Knowi capabilities. After the first live batch, Knowi creates an App Events - <App name> dataset in the owner's account. Use it in Knowi queries, dashboards, reports, and alerts.
The App's App activity also includes its successful Knowi sign-ins from Core, with the person's name when available. Select Knowi sign-ins to see these records and the Sign-ins count. New sign-in records cover password/MFA, SSO, and signing into the App using an existing Knowi session. Impersonated View as sessions remain separate. These Core records do not require an App Events dataset and are not copied into it.
Open App activity to review the App across all versions. Choose Last 24 hours, Last 7 days, or Last 30 days, then filter by event type. The page shows up to the latest 100 activities matching those filters; its counts cover only the activities shown, not all usage in the selected period. Use the App Events dataset for broader usage analysis, subject to its normal sharing and data permissions.
Activity groups related request, capability, and write records using their shared request identifier. Each group shows one result, such as Completed, Conflict: record changed, or Access denied, and the person's name when available. Older write records without a shared identifier remain separate; Knowi does not guess which requests they belong to. Expand an activity for its recorded details, including a request ID or rows changed when available.
Ask the builder to track a business action, for example: "Track when someone exports the sales results." You can also ask for an Activity page backed by the events dataset. Share that dataset only with people who should see its records. Runs of saved write actions land in the same dataset as knowi.write rows with the action key, outcome, request ID, and rows affected.
Preview, authenticated PDF rendering, and impersonated View as sessions do not contribute usage events. Anonymous PDF renders of Public Apps can count as page views. Events can be lost during overload or failures, so use them for usage analysis rather than an audit record. See custom event code and limits.
Troubleshooting
Start with the status or error shown in the App editor, or ask your MCP assistant to check the App's status.
| Problem | Next step |
|---|---|
| Apps is unavailable or hidden | Ask your Knowi account representative to enable Apps and AI Agents access. If they are enabled, ask your administrator to check your App permissions. |
| Generation asks for a repository | On a new App, open Advanced settings > Repository; on an existing App, open App settings > Repository. Create or choose a Knowi-managed repository, or ask an administrator to make one available. In MCP, ask the assistant to run setup and follow its missing-setup instructions. |
| My dataset is missing | Confirm you can open it in Knowi. Ask its owner to share it if needed. In MCP, give the assistant the exact dataset name and resolve any ambiguous matches. |
| The source has newer changes | Select Build latest source and wait for the new version to become Ready. Return to Builder and retry your saved request. Existing requests and versions remain available. |
| Generation or build failed | Read the error shown with the failed version. For an AI-generated App, describe the error in Ask for a change or give it to your MCP assistant and request a correction. If it concerns repository access, ask your administrator to restore access. If it persists, send the App name, version or commit, and error to Knowi Support. The working live version stays available. |
| The new change is not visible | Check that the new version is Ready and selected in the preview. If you are looking at the live URL, publish the reviewed version. If you changed code in Git, select Build or ask MCP to build the latest commit first. |
| A preview link has expired | Open the version's preview again from Knowi, or ask your MCP assistant for a fresh preview link. |
| An AI response, email action, or save appears to do nothing in preview | Check Preview versus live. Those features can return a dry-run result; managed storage and secrets are unavailable in preview. |
| Publish is unavailable | Wait for a Ready version. Ask your administrator to confirm publish permission and write access to the App. If using managed storage, its status must also be Ready. |
| Knowi sign-in is greyed out | Sign-in for Apps has not been configured in your Knowi environment. Ask your administrator or Knowi Support to enable it. The New app form selects Public in this case, which allows anyone with the published URL to open the App. |
| A colleague cannot open the live App or sees different data | For a Knowi sign-in App, share the App with the colleague and check their access to its datasets or dashboards. Row-level restrictions can intentionally show them different results. An authorized administrator can use View as to inspect their access. |
| An App is missing from my Apps list | Ask the owner to share it with you. Administrators also need ownership or sharing to see it in the management list. |
| An image upload fails, or an old logo remains | Check the error and the file type and size in Attach design references and brand assets, then attach a failed upload again. To replace a logo, attach the new file as a brand asset, request the replacement, then generate and publish the new version. |
MCP cannot find knowi_app
|
Check that your client is connected to the correct Knowi deployment and account, then ask your administrator to verify Apps enablement and your permissions. |
| I cannot create another App | Your account may have reached its App limit. Contact your Knowi account representative. |
| Add action is disabled or lists no destination | Ask a datasource administrator to check Writable Destination on a SQL Server connection you can edit. DBWrite must be enabled for the account, and the App must use Knowi sign-in. |
| A user sees "Write action access was denied" | Confirm the user has current App access and the action is enabled. The action author must still have App editing and writable-destination permissions. |
| A user sees "Trusted write action scope is unavailable" | The action has a value named after a filter field, and this user has no single enabled Equals filter with that name. Add the user or group filter, then try again. |
| A write action returns conflict or unknown | Conflict means no row matched, usually because the record changed since it was loaded; reload it and try again. Unknown means the database did not confirm the commit; check the record before retrying. Use App activity to look up the request ID in the recorded event details. |
For setup, code, DNS, database, and embedding errors, see technical troubleshooting. Contact Knowi Support with the App name, repository name, version or short commit, current state, and error message. Do not include secrets or customer data.
Administration
Permissions
Your administrator assigns these permissions. Editing or publishing a shared App also requires write access to that App; a permission alone does not share it with you.
| Permission | Allows |
|---|---|
apps:view |
Open the Apps area and see Apps you own or that are shared with you. |
apps:edit |
Create and edit Apps, generate changes, build, preview, and manage settings. |
apps:publish |
Publish, roll back, apply live access or custom-domain changes, show the App in the Knowi menu, and manage embedding settings. Embedding also requires apps:edit. |
apps:share |
Share an App with Knowi users and groups. |
apps:delete |
Remove an App. |
Saving a write action requires apps:edit, write access to the App, edit access to the destination datasource, and DBWrite enabled for the account. Running one requires Knowi sign-in and current access to the App. Reviewing write activity in Queries uses the App Events dataset's access permissions.
Choose where the source lives
Every App's code lives in a Git repository. Knowi saves the exact source revision for each generated version, so developers can review and test it independently.
Knowi-managed is the starting option for teams that want Knowi to create a private repository. A dedicated repository per App keeps source and releases easier to manage. Your organization can also use GitHub or another Git server over SSH, when enabled. App sharing and repository collaborator access are separate.
See repository setup for GitHub authorization, SSH deploy keys, and collaborator access.
AI provider
App Generation uses an external AI provider. Knowi chooses a suitable model unless an administrator configures a customer-provided model under AI Settings with that provider's API key. App Generation is not hosted entirely in-house. This setting is separate from adding AI text features to the App itself.
Code and integrations
Use this section when you need to edit App source code, connect a Git repository, call APIs from an App, or embed it in a portal. It includes the supported stack, code examples, API limits, and deployment settings.
Use the knowi_app MCP tool
The MCP walkthrough shows a complete conversation. Your client calls knowi_app with one of the actions below. MCP uses your authenticated Knowi identity and App permissions; repository and asset access are checked on each operation.
| Action | What it does |
|---|---|
setup |
Lists authorized repositories and any remaining setup requirements. |
create |
Creates an App shell. Requires name and slug; select an authorized source or create a repository with repository: "knowi_managed" when setup permits. Follow with read and change to save and build the first version. |
read |
Requires appId. Returns source files, the exact parentCommit, the App contract, and recent shared change summaries and notes. |
change |
Requires appId, parentCommit from read, files, and a short commit message. Commits the calling assistant's code and queues a build. Omitted files remain unchanged; a null file value deletes that file. Declare the complete desired bindings in app.json. Optional intent and handoff notes are shared with App collaborators. Read again after a source conflict. |
status |
Requires appId, with optional jobId. Poll while done is false. A Ready result includes the versionId needed to preview or publish. Status never starts a preview. |
build |
Requires appId. Builds the repository's current commit without generating source; poll status for the Ready version. |
preview |
Requires appId and a Ready versionId. Explicitly starts that version's preview and returns a short-lived URL. Call only when the user requests a preview. |
publish |
Makes a Ready version live. Requires appId, its versionId, confirm: true, and an explicit user request to publish. |
secret |
Saves an App secret using appId and secret: {name, value}. Removal uses secret: {name, remove: true} and confirm: true. Changes take effect at the next publish; previews do not receive secrets. |
If exactly one writable repository is available, create can select it automatically. Otherwise, use the repository label returned by setup. When knowiManagedRepositoryAvailable is true, create can provision a repository with repository: "knowi_managed". For SSH, use repository: "ssh" and remoteUrl; authorize the returned deploy key with write access, then call create again with the returned source label. MCP resolves it only against repositories already authorized for the account and requires the appropriate user permissions.
Use dataset and dashboard search tools to resolve the user's requested data, then declare the complete selected bindings in the app.json file submitted with change. Resolve ambiguous matches with the user. Knowi checks the editor's access for preview and the publisher's access at publication; live data access follows the App's access mode.
Commits and handoffs: Knowi records observed commits, builds, and publishes from any MCP client. Optional intent and handoff notes are limited to 2,000 characters each, shared with App collaborators, and attached to the resulting commit. read returns recent shared changes and marks notes from earlier commits as stale. The App's Commits view shows these notes with the version; Refresh loads changes made in Claude, Codex, or another client. Git authors, authenticated requesters, and publishers are distinct. Client names are advisory attribution; permissions come from your authenticated Knowi identity. Private conversations in Knowi remain separate, and external chat transcripts are not automatically imported. Do not include private chats or secrets in shared notes.
OAuth and manually generated MCP tokens use the same Knowi role and App permissions. There is no separate Apps token or knowi.apps scope.
After publishing, the response includes the App ID, live URL, and declared pages. The agent can pass the App ID and page path to create_report for a schedule or create_alert for a conditional notification. For example: "Build an operations review and email its Overview page to the leads every Monday." Knowi's existing Reports and Alerts services own delivery and scheduling.
Publishing through MCP requires apps:publish and the same App permissions as publishing in the UI. create and change can configure access and managed storage when authorized. MCP cannot remove an App, select an unauthorized repository, or upload built output.
Repository setup
Choose the source under Advanced settings > Repository on the New app screen, which offers the source options enabled for your account. On an existing App, open App settings > Repository to see the connected repository, branch, latest commit, and build and release state; see Settings.
| Option | Best for | Setup |
|---|---|---|
| Knowi-managed | Teams that want to start without setting up their own Git hosting. | Enter a repository name and select Create repository. Knowi creates a private repository and selects it for the App. |
| GitHub | Organizations that keep source in their own GitHub account. | Select Connect GitHub, authorize only the repositories Knowi Apps may use, then select Check again. Writable repositories appear in the list. |
| Other Git (SSH) | GitLab, Bitbucket, Azure DevOps, Beanstalk, or a self-hosted Git server. | Enter the SSH remote and optional branch, generate a deploy key, add it to the repository, and select Verify. |
Options that are not enabled for your account do not appear.
Knowi-managed repositories
Repository names use 3-60 lowercase letters, numbers, and hyphens. To let a teammate clone, review, or push, open Manage access and add their GitHub username with Read and write or Read only collaborator access. You can remove access from the same list.
GitHub
A GitHub administrator installs the Knowi GitHub App and chooses which repositories it may use. Knowi sees only the selected repositories. Allow write access if Knowi AI or MCP will commit changes. To change access later, update the selected repositories in GitHub and select Check again in Knowi.
Other Git over SSH
- Enter an SSH remote such as
git@host:group/repo.gitorssh://git@host/group/repo.git. Leave the branch empty to use the repository's default branch. - Select Generate deploy key, then copy the public key shown.
- Add the public key to that repository as a deploy key with write access.
- Select Verify. Knowi confirms that it can read and write the repository and shows the pinned host-key fingerprints.
Once verified, the repository is listed under Other Git (SSH), above the form for adding another remote. A read-only key remains pending until write access is granted. Pending repositories remain listed with Verify and Remove actions. Knowi does not ask for your Git password or personal access key.
Work with source and build locally
The repository is the source of truth. Your team can clone it, create branches, use pull requests, test locally, merge into the configured default branch, and inspect the commit used for each App version. After merging a change, select Build in Knowi.
Supported stack
- Frontend: HTML, CSS, JavaScript, or a frontend framework that builds through the project's npm script.
- Backend: a Node.js 22 HTTP service. Express, Fastify, Nest, and other pinned npm packages are supported.
- Storage: optional Managed PostgreSQL for App-owned workflow data.
The backend can define API routes, accept file uploads, call external APIs, send outbound webhooks, and perform request-driven work allowed by your account's App policy. It must listen on process.env.PORT and must not hard-code a deployment port.
Repository contract
| File | Purpose |
|---|---|
app.json |
Build declaration. |
package.json |
Build script and dependencies. |
package-lock.json |
Locked dependencies. |
<web source> |
Your frontend source and assets. |
server/app.mjs |
The service entry in the generated scaffold. |
db.json |
Optional additive managed-database schema. |
app.json identifies the service entry produced by the build, the optional database schema, and the exact governed capabilities used by that source version:
{
"v": 2,
"service": "dist/server.mjs",
"db": "db.json",
"reportPages": [
{"path": "/", "title": "Overview"},
{"path": "/incidents", "title": "Incidents"}
],
"bindings": [
{"key": "sales-orders", "type": "data", "id": 1234},
{"key": "sales-overview", "type": "dashboard", "id": 5678},
{"key": "crm", "type": "http", "connection": "crm-production"}
],
"branding": {
"name": "Oakland Case Work",
"logo": "web/assets/logo.svg",
"colors": {"background": "#0b1b2b", "button": "#2f6df6", "buttonText": "#ffffff"}
}
}
The service value is a relative .js, .mjs, or .cjs path that must exist after the build. The generated scaffold uses server/app.mjs directly. bindings is required; use [] when the App needs no governed capabilities.
Each binding has a stable key that App code uses, such as data.query({binding: "sales-orders"}). The key is only a source-level name - it is not an API key or secret. data and dashboard bindings identify an exact Knowi asset. http and workspace bindings refer to an existing App connection, keeping destinations, policy, and encrypted credentials outside Git. An App may declare up to 64 bindings; keys and connection names are 1-64 letters, digits, ., _, or - and must start with a letter or digit.
branding is optional and applies only to a Knowi sign-in App; see Sign-in branding.
reportPages gives each reportable page a path and a display title. report.send and report.schedule accept only these pages, so the declaration decides what the App can report on. The generator writes it; teams editing source maintain it in app.json. Declare between 1 and 64 pages, each with a distinct path and a title up to 120 characters. Paths must be absolute App paths such as /incidents, without a query string, fragment, traversal, or reserved /__knowi route. Older manifests without reportPages expose / as Home. Rebuild and publish to change the list. Page parameters travel in the request's own query field, not in the declaration.
The manifest is versioned with the source, so restore, rollback, Git review, and AI regeneration all use the same declarations. Knowi validates them during build, rechecks the editor's access for preview and the publisher's access at publish, and permits only the bindings declared by the exact running version. The App never receives a Core API key, datasource password, or connection secret.
Build locally with Node 22, npm, the checked-in lockfile, and the declared build script:
npm ci --ignore-scripts --no-audit --no-fund npm run build
Use the App's governed Knowi API for datasets, dashboards, approved HTTP actions, and bounded state. Data writes are accepted only while handling a same-origin mutating request, not from a GET handler. The App may also use its own routes and approved integrations.
When generating an App, Knowi supplies the supported capability catalog and the App's approved bindings so the builder can wire the right calls. Generated code calls these capabilities through the gateway; Core enforces the current identity, asset permissions, connection credentials, AI credit controls, and report permissions. Knowing a capability name does not grant access to it.
App-owned database queries and ordinary external HTTP calls are separate runtime paths. Managed PostgreSQL uses the App's restricted database connection, and external requests follow runtime egress policy. They do not all pass through Core's capability API. Use http.request when an integration needs a governed Knowi connection and its stored secret.
These governed capabilities are available to App server code:
The examples use invoke(req, capability, payload) for the generated source's gateway helper. Use the helper in your App's source to carry the current request identity.
| Capability | Binding it uses | What it does |
|---|---|---|
data.query |
data |
Reads rows from a selected dataset with governed fields, filters, sorting, and paging. |
dashboard.embed |
dashboard |
Mints a short-lived secure URL for the bound dashboard. The App receives an embed URL without the viewer's entitlement filters. The dashboard does not display while the App is itself embedded in another site; see Embed an App in your site. |
workspace.embed |
workspace |
Mints a short-lived Agentic BI workspace URL over the datasets the connection allows. Its lifetime is 2 to 30 minutes, 10 by default. |
http.request |
http |
Calls the connection's base URL with a method the connection allows. Knowi injects the stored credential; redirects are not followed and only public hosts are reachable. |
action.execute |
action |
Runs a saved write action against a writable SQL Server connection with validated inputs, in one transaction that must change exactly one row. See Run a saved write action from an App. |
ai.generate |
ai |
Generates text through the account's configured Apps AI provider, with Knowi credit and timeout controls. |
report.send |
Current App and signed-in user | Emails one App page as a PDF once. |
report.schedule |
Current App and signed-in user | Creates a recurring App PDF email report managed by Core. |
events.track |
None | Queues a named usage event through the gateway. See App activity and custom events for limits and delivery behavior. |
state.get / state.set
|
None | Reads and writes small App-scoped JSON values, up to 8 KB per key, 128 keys, and 256 KB per App. Use Managed PostgreSQL for anything larger. |
A dashboard embed URL defaults to a 30-minute lifetime and can be minted for as long as the App session lasts. Outbound http.request bodies and responses are capped at 8 KB each.
data.query applies filters and sorting inside Knowi, before rows reach the App. For example, an App server route can request only the fields and rows it needs:
const page = await invoke(req, "data.query", {
binding: "sales-orders",
fields: ["Order Date", "Region", "Revenue"],
filters: [{field: "Region", operator: "eq", value: "West"}],
sort: [{field: "Order Date", direction: "desc"}],
limit: 1000,
offset: 0
});
Filter operators are eq, neq, gt, gte, lt, lte, isNull, and isNotNull. Combine gte and lte filters for a range. Field names must come from the selected dataset. A direct dataset's declared runtime tokens may also be passed as eq filters using the exact runtime-token name shown in its binding metadata. The response contains columns, row arrays in rows, and truncated. When truncated is true and nextOffset is present, use that exact offset for the next request. Knowi always adds the effective viewer's customer, group, user, shared, and macro content filters; App filters can narrow that authorized result but cannot replace those rules.
The default limit is 1,000 rows and the maximum is 200,000. Large or wide results may reach the response-size limit first; in that case, continue from nextOffset rather than increasing the limit.
Local testing does not deploy an App. Commit the source and select Build in Knowi; prebuilt output cannot be uploaded as a release.
Managed database schema
An App can use a pinned PostgreSQL client. Its database access is limited to that App. A release may declare an additive schema in db.json; schema changes are applied before the release goes live. A schema failure leaves the current version unchanged. Preview does not use the live managed database, and rollback changes code without rolling data backward.
Runtime access and isolation
The access mode determines whether requests carry a Knowi viewer identity. Public and App-managed visitors are anonymous to Knowi; an explicitly selected dataset can be exposed through an App-level grant checked against the publisher's current dataset access and content filters. Private dashboard bindings require Knowi sign-in.
Selecting App manages access does not create authentication. App source must implement and configure its own login and sessions. Use secure, server-managed cookies, rotate sessions after login, and keep session identifiers out of browser JavaScript.
Application files are read-only while deployed, resources are bounded, and outbound access follows the account's App policy. App code does not receive Knowi browser sessions, datasource credentials, source-host access, or another App's secrets.
Report pages and PDF rendering
For reliable PDFs, set window.knowiReportReady = false before loading page data, then set it to true after rendering completes. A declared readiness flag that never becomes true causes the render to fail. Pages without the flag use network-idle readiness. Use @media print to hide navigation and action buttons.
The alert condition belongs to a dataset. Attaching an App PDF does not make the alert monitor that page or track individual incidents. Current duplicate suppression compares alert results; it does not track each delivered record. Alert data attachments are CSV, not Excel files. MCP create_alert does not create anomaly alerts; use the Alerts UI for existing anomaly alerts.
Secrets
On an existing App, open App settings > Secrets, enter a name and value, and select Save. This requires App edit permission and write access to the App. Server code reads the value through an environment variable such as process.env.CRM_API_KEY after the next publish. Previews do not receive secrets. Replacing or removing a secret also takes effect at the next publish.
Keep credentials out of prompts, Git, browser code, and logs. When asking the builder to use an integration, refer to the secret's name. For a connection already managed by Knowi, prefer the http.request capability, which injects that connection's stored credentials.
Runtime actions
AI text inside an App
Ask for an AI feature in the Builder, such as "summarize the selected incidents", and Knowi turns AI on for that App. AI then appears under Data as AI text generation. A Builder change keeps AI only while the App's server code calls ai.generate; to turn it off, ask the builder to remove the AI feature. An App edited outside the Builder declares one AI binding in app.json, for example {"key":"assistant","type":"ai"}. App server code can then call:
const result = await invoke(req, "ai.generate", {
prompt: "Summarize these selected incidents: " + JSON.stringify(incidents),
system: "Use only the supplied records. Keep the summary brief."
});
The request contains prompt and optional system; the result contains text. This is text generation, not an automatic call to the full Knowi agent or a tool-execution session. Query the authorized data first and supply the context needed for the answer. Render the returned text safely.
The provider comes from the granting user's AI Settings Apps configuration. Knowi applies the customer's credit controls, a 60-second timeout, and the 16 KiB capability envelope; keep the combined prompt and system text under 12 KB. Preview returns dryRun: true and does not call the provider.
Send or schedule a report from an App
An App can expose Email this report and Schedule delivery buttons that call its server. The server invokes report.send or report.schedule while handling that user's same-origin POST request. Live calls require a Knowi sign-in App and a user with permission to create reports, send reports by email, and view the current App. Public and App-managed requests have no Knowi viewer identity for these hooks. Core derives the App and user from the request; the payload cannot select an appId, userId, or reportAs identity.
Send one PDF without saving a schedule:
const result = await invoke(req, "report.send", {
page: "/incidents",
query: "region=west",
sendTo: "leads@example.com",
replyTo: "operations@example.com",
subject: "Latest incidents",
body: "The current incident review is attached."
});
Create a recurring report in Core:
const result = await invoke(req, "report.schedule", {
name: "Weekly incident review",
page: "/incidents",
query: "region=west",
sendTo: "leads@example.com",
subject: "Weekly incidents",
schedule: {
frequencyType: "weekly",
frequency: 1,
dayOfWeek: "MONDAY",
startTime: "08:00",
timezone: "America/Los_Angeles"
}
});
sendTo is a required comma-separated email list. Both hooks accept optional page (default /), query, from, replyTo, cc, bcc, subject, body, and name. Omit from to use the configured sender. If supplied, it must be the signed-in user's email or a sender configured for the account; arbitrary sender impersonation is rejected. These hooks send email with one App PDF, not CSV or Excel attachments.
For report.schedule, schedule.frequencyType is daily, weekly, monthly, hours, or minutes. frequency is a positive integer, defaulting to 1. Supply startTime as HH:mm; timezone defaults to the user's timezone. Weekly schedules require an uppercase weekday such as MONDAY; monthly schedules require dayOfMonth from 1 to 28. The resulting report belongs to the signed-in user and can be edited or removed in Reports. Future runs continue through Core without keeping the App page open.
Successful sends return {"status":"sent"}; saved schedules return {"status":"scheduled","reportId":123}. Preview returns {"dryRun":true,"status":"preview"} and neither sends nor saves. Show these outcomes accurately in the App. Do not call delivery hooks automatically when a page loads, and do not retry a timed-out send automatically: it may already have sent. Calls made while a report PDF is rendering are rejected to prevent recursive delivery.
Run a saved write action from an App
A saved write action reaches the builder as an action binding with its key and its App-input definitions. Server code runs it while handling the user's same-origin POST, PUT, PATCH, or DELETE request; a GET handler cannot call it:
const result = await invoke(req, "action.execute", {
binding: "approve-order",
input: { orderId: 101, status: "approved", expectedVersion: 3 }
});
input holds only the form values, keyed by plain name ($c9_orderId$ uses orderId), with JSON types matching their declared types: strings for text, numbers for integer and number, and true or false for boolean. Unknown keys, missing required values, and values outside the declared limits are rejected before any database call. Core fills the signed-in user's values from their user and groups, with no fallback to App input. The request cannot choose a datasource, SQL, or authenticated identity.
A success returns {"requestId":"...","outcome":"succeeded","affectedRows":1}. Preview returns {"requestId":"...","outcome":"preview","dryRun":true} without touching the database. Every other outcome is an error whose body carries the same requestId and outcome plus an error message:
| Outcome | Status | Meaning and what the App should do |
|---|---|---|
rejected |
400, 403, or 429 | Invalid input, a user without App access, a disabled action, an unavailable destination, or the rate limit. Nothing was written. Correct the input or tell the user they are not allowed. |
conflict |
409 | The statement matched no row, usually because the record changed since it was loaded. Nothing was written. Reload the record and let the user try again. |
failed |
502 | The statement failed or would have changed more than one row. The transaction was rolled back. |
unknown |
502 | The database did not confirm whether the commit happened, for example after a timeout. Do not retry automatically; read the record back first. |
Show the outcome to the user and keep the requestId in the App's own error reporting so support can find it in the App Events dataset through App activity. Do not run write actions when a page loads, and do not retry a failed or unknown outcome without checking the record.
Each App may run 120 write actions per minute and 4 at a time; a statement is cancelled after 30 seconds. A saved action has at most 32 parameters, text values up to 2,048 characters, and at most 100 allowed values per parameter. Write actions are refused during report PDF rendering and in View as user sessions, and they require a Knowi sign-in App.
Sign-in branding configuration
A Knowi sign-in App can brand its own hosted sign-in and MFA pages so the login looks like the App instead of like Knowi. The branding is declared in the source manifest, under branding in app.json, and is stored with the built version, so each version keeps the branding it was built with.
| Key | Value |
|---|---|
name |
Display name on the sign-in page, up to 80 characters. |
logo |
Repository path to an SVG, PNG, JPEG, or WebP file no larger than 64 KB, usually a brand asset under web/assets/. |
colors |
Any of background, surface, text, muted, border, button, and buttonText, each a 3- or 6-digit hex value such as #0b1b2b. |
Branding is validated strictly: an unknown key, a malformed color, or a logo that is oversize or not an image fails the build rather than shipping an unbranded page. AI writes branding when you describe it, and picks the logo from the brand assets attached to that request. A later change that attaches no new logo keeps the one the App already has; replace a logo by attaching another brand asset and naming it.
Image validation and asset paths
One generation can carry up to four design references and four brand assets, totaling 8 MB across both. An App can hold up to 12 uploaded images, totaling 24 MB, that no generation has used yet. Remove one before adding another if you reach that.
Knowi reads each image's real type from its bytes and rejects a file whose extension does not match. PNG files must be no more than 4,096 pixels on a side and 12 megapixels. SVG is stored and served exactly as uploaded, so it is accepted only when it carries no active content: no <script>, no on... event attributes, no javascript: URL, no <foreignObject>, and href values limited to #fragment or data:image/.
Knowi derives a brand asset's committed file name from the file you upload: lowercased, unsupported characters folded to hyphens, the extension set from the detected image type, and the base trimmed to 48 characters. When the App already has that name, a -2, -3 suffix is added. The list shows the final /assets/<name> path once the upload finishes; use that exact path in later prompts and in App code.
Both kinds are consumed by the generation that uses them. After the version is created, Knowi discards the stored image bytes: a design reference leaves nothing behind, and a brand asset lives on in Git, so every later version keeps serving it without another upload. Upload a brand asset again only to add or replace one.
Remove an image from the list before generating if you change your mind. An image a generated version already used cannot be removed, and a used brand asset keeps its name reserved so a later upload does not collide with it.
Custom domains
Every App is served at https://<slug>.apps.knowi.com. You can also attach one domain you own, such as oaklandcw.com or app.oaklandcw.com; the Knowi URL keeps working alongside it.
- Open the App by selecting its name in the Knowi Apps list, or select Edit app from the row's ... menu. Open App settings > URL & domain and find Custom domain. Enter the domain (any scheme or path is stripped) and select Save.
- Prove ownership. Add a DNS TXT record at
_knowi-verify.<domain>with the value shown under Custom domain, then select Verify. The status changes from Pending verification to Verified. DNS propagation can take several minutes; select Verify again if it fails. - Point the domain at Knowi. Add a CNAME record for the domain with the value
domains.apps.knowi.com.
| Type | Name | Value |
|---|---|---|
| TXT | _knowi-verify.<domain> |
The verification token shown under Custom domain |
| CNAME | <domain> |
domains.apps.knowi.com |
After verification, a published App is republished automatically so it answers on the domain, and a TLS certificate is issued through Let's Encrypt within a minute or two. Until then, browsers may show a certificate warning. If the App is not published yet, the domain takes effect on the next publish. Knowi sign-in works on the custom domain; the login page is served on the App's domain and sessions are per domain. Preview URLs (preview-<slug>.apps.knowi.com) never use the custom domain.
Apex domains: A root domain such as oaklandcw.com cannot use a CNAME record. Where your DNS provider supports CNAME flattening or ALIAS/ANAME records (Cloudflare, DNSimple, NS1, and similar), point one at domains.apps.knowi.com. On Route 53 or other providers without that option, attach a subdomain such as www.oaklandcw.com with a CNAME and redirect the root to it, or contact Knowi support for an A-record target.
Changing or removing: Change replaces the domain and issues a new verification token, so repeat the TXT verification for the new domain. Remove detaches the domain; the App stops answering on it as soon as the republish completes, and the Knowi URL keeps working.
Limits:
- One custom domain per App, and a domain can be attached to only one App across all Knowi accounts. A domain saved but left unverified for 72 hours can be claimed by another App, which removes it from yours; verify promptly or save it again when you are ready.
- Domains under
apps.knowi.comorknowi.com, and IP addresses, are rejected. - Saving a domain requires App edit permission. On a live App, verifying the domain, or changing or removing a verified domain, also requires publish permission because the live App is republished.
- On-premises deployments must configure the Knowi Apps runtime with a certificate issuer (
KNOWI_APPS_K8S_CUSTOM_DOMAIN_ISSUER). Otherwise, verifying the domain on a live App shows an error that includes "Custom domains are not enabled on this runtime", the domain stays in Pending verification, and the App keeps publishing normally on its Knowi URL; saving alone never contacts the runtime. Contact your Knowi administrator.
Embedding setup and code
A published App can be shown inside your own web page, in an iframe, so your users see it without leaving your portal. Embedding is off until you turn it on, and only the sites you list are allowed to show the App; every other site is refused by the browser.
Open the App, select App settings > Embedding, and select Allow this app to be embedded. This requires edit and publish permission. List each site that may show the App, one per line, up to eight, then select Save. A site is a scheme and host, for example https://portal.example.com. The scheme is optional and https is assumed. Paths, query strings, wildcards, and ports are not accepted, so list each host separately, such as https://portal.example.com and https://www.example.com. Plain http is accepted only for localhost while you develop.
Publish the App if it has no live version. For a live App on the current runtime, saving the embedding settings applies them without a republish. If the panel reports that an older runtime cannot serve embedding, select Republish to update the runtime while keeping the same App version. Turning embedding off, or removing a site from the list, stops that site from showing the App on its next load.
Embedding is available for Apps that use Knowi sign-in required or Public access. For an App that uses App manages access, the panel shows that embedding is not available.
The panel generates the snippet to paste into your page, and the Copy button copies it. The snippet matches the App's access mode: a plain iframe for a Public App, or a Knowi.render call for a Knowi sign-in App. Use the Address to embed control to choose between the App's Knowi address and its custom domain, which appears when the App has one. Embedding under a custom domain that sits inside your own domain keeps the viewer's session first-party; see the browser table below.
Embedding a Knowi sign-in App
Your own server mints a session token for the viewer with the Knowi single sign-on API, exactly as it does for an embedded dashboard; see Single Sign-On. Hand that token to the page and render the App:
<script src="https://www.knowi.com/minify/knowi-api.min.js"></script>
<div id="orders-app" style="height: 100vh"></div>
<script>
Knowi.render('#orders-app', {
type: 'appSso',
url: 'https://orders.apps.knowi.com/',
token: '<sso_session_token>',
onSessionExpired: function () { /* render again with a fresh token */ },
onError: function (reason) { console.error('Knowi embed failed', reason); }
});
</script>
The url is the App's own address and is all that identifies it; there is no App id to pass. It must be the App's origin only: https, with no path, query string, or credentials. The token is posted to the App, never placed in a URL, and the App's own code never receives it. The viewer must be a Knowi user in the App's account who has access to the published App, and they are subject to that user's groups, roles, and row-level restrictions. Every viewer of a Knowi sign-in App is therefore a Knowi single sign-on user.
Each render starts a new session, so mint a fresh token for every page load, including reloads. This is also how you switch users: render again with the new viewer's token. Call Knowi.logout(container) when the viewer signs out of your portal. Rendering into a container that already holds an App replaces it.
An embedded session lasts up to one hour, and ends sooner if the single sign-on token it was created from expires sooner. It is never renewed by the App. A token that has expired cannot start a session, and neither can a token that was already used to sign in to a dashboard when the deployment enforces single-use tokens (ssoTokenSingleUse). In either case the frame shows a short "could not verify your sign-in" page. Starting an App session does not itself use up the token, so do not rely on it for replay protection; keep token lifetimes short. Repeated rejected attempts against one App are temporarily throttled.
When a session ends, the App tells your page by posting a knowi:sessionExpired message, which arrives as the onSessionExpired callback above. Render again with a fresh token to continue.
The Knowi.render call for an App accepts these options in addition to type, url, and token:
| Option | Purpose |
|---|---|
onSessionExpired(container) |
Called when the viewer's session ends. Render again with a fresh token. |
onReady(container) |
Called when the frame finishes loading. It does not mean the App finished rendering. |
onError(reason, container) |
Called with a short code: storage-blocked when the browser refused to store the session for a frame on another site, embed-rejected when the App refused the sign-in, or timeout when the frame never loaded. Do not render again from storage-blocked; it will repeat. |
onMessage(data, container) |
Called for any other message the App posts to your page. Only messages from that App's own frame are delivered. |
title |
The iframe title, for screen readers. Defaults to Knowi app. |
timeoutMs |
How long to wait for the frame before reporting timeout. Defaults to 20000. Applies only when onError is set. |
App embedding needs a current browser; Internet Explorer is not supported. Give the container an explicit height, since the frame fills it.
Embedding a Public App
A Public App needs no token and can be embedded with a plain iframe:
<iframe src="https://orders.apps.knowi.com/" title="Orders app" width="100%" height="800" frameborder="0"></iframe>
Knowi.render accepts it too, with type: 'appPublic', if you prefer one API for both.
What to expect
| Situation | What happens |
|---|---|
| Several Apps on one page | Supported. Render each into its own container; the sessions are separate, and one App's session cannot open another. |
| A site that is not on the list | The browser refuses to show the App. Add the site to the list and reload. |
| Safari, or any browser set to block third-party cookies | A Public App embeds normally, because it needs no sign-in. A Knowi sign-in App cannot keep the viewer signed in inside the frame when it is on a different domain than your page: those viewers see a short page with a link to open the App in its own tab and sign in there. Serving the App from a custom domain under your own domain avoids this. |
| An App using App manages access | Cannot be embedded. A framed viewer is not a Knowi user, so Knowi cannot vouch for them to the App. |
| A Knowi dashboard shown inside the App | Does not display while the App is itself embedded in another site. The rest of the App works normally. |
Embedding does not grant App access. The access mode and, for Knowi sign-in Apps, App sharing still decide who may open it, and a Knowi sign-in App still applies that viewer's users, groups, roles, and row-level restrictions.
Custom event code and limits
The App's Activity view groups recorded requests across all versions and includes Knowi sign-ins. Its counts cover only the activities shown. Sign-in records are stored separately from the App Events dataset described below.
Published Apps automatically record HTML page views, capability names with status and response time, and HTTP request errors. The runtime gateway records these consistently across Apps. Static asset requests do not count as page views; a browser-only route change in a single-page App needs a custom event.
Core creates App Events – <App name> as a Knowi dataset in the App owner's account after the first live batch. Use it in normal Knowi queries, dashboards, reports, and alerts. It includes the event time, App/version, request ID, page path, status/duration where relevant, and the signed-in Knowi user ID. Public and App-managed visitors have no Knowi user ID. Preview, authenticated report rendering, and View as user sessions do not contribute usage events. Anonymous renders of Public Apps can count as page views.
Ask the builder to add a named event for a business action, for example, “Track when someone exports the crime results.” Server actions call the events.track capability through the same gateway helper as data.query:
invoke(req, 'events.track', {
name: 'results.exported',
properties: { format: 'xlsx', resultCount: 12 }
});
Browser interactions can send a beacon directly to the App gateway:
navigator.sendBeacon('/__knowi/events', new Blob([JSON.stringify({
name: 'filter.changed',
properties: { radiusFeet: 300 }
})], { type: 'application/json' }));
Custom events require a same-origin POST (or a server action handling a same-origin PUT, PATCH, or DELETE). The gateway supplies identity; App-supplied App or user IDs are ignored. Names are at most 64 characters using letters, numbers, periods, underscores, and hyphens, beginning with a letter; knowi. names are reserved. Properties allow at most 16 scalar values, with strings up to 512 characters and a 4 KB event limit. Do not send addresses, emails, secrets, tokens, cookies, query strings, or other sensitive user data.
Live requests return {accepted:true} when queued, or {accepted:false} if the queue is full. Preview, authenticated rendering, and View as user return {dryRun:true}. Acceptance means queued, not durably stored. Events are batched every 10 seconds or 200 events, with bounded memory and failure backoff. A restart, overload, or storage failure can lose events; this is usage analytics, not an audit log.
To show an Activity page inside the App, select this dataset as an approved data binding and use data.query. Share the dataset with its intended viewers; their permissions and content filters still apply. Do not give a Public App a binding that exposes raw visitor activity or user IDs. If the owner deletes the event dataset or removes access, collection stops; it is not silently recreated.
On-premises and GitHub Enterprise Server
Custom-domain DNS records and limits are described in Custom domains. On-premises operators must configure a certificate issuer with KNOWI_APPS_K8S_CUSTOM_DOMAIN_ISSUER before a live App can use a custom domain.
On-premises deployments can use GitHub Enterprise Server when it is enabled by the Knowi administrator. Other Git (SSH) is also available when enabled. Contact your Knowi administrator or account representative before setup.
View as user requires matching Core and runtime support. Operators must update the runtime gateway before enabling the Core change so the identity banner, expiry controls, and analytics exclusion are available.
Technical troubleshooting
| Problem | What to check |
|---|---|
| Knowi Apps is unavailable, or the Apps page says it is not turned on for this account | Contact your Knowi account representative and ask to have Knowi Apps turned on, or select Request access on that page. |
| Knowi Apps is enabled but hidden | Confirm the account has AI Agents access, then ask a Knowi administrator to verify your Knowi Apps permissions. |
| A source option is missing | Ask a Knowi administrator whether that option is enabled for your account. |
| GitHub repository is missing | Select it in the Knowi GitHub App installation, allow write access, then select Check again. |
| SSH verification fails | Confirm the remote is correct, the deploy key has write access, and the host is reachable over SSH. |
| AI cannot commit | Check repository write access and branch-protection rules. |
| A custom generation model is unavailable | Ask an administrator to add that provider's API key or clear the App Generation selection under AI Settings to let Knowi choose the default frontier model. |
| The AI provider has insufficient API credit | Add credit to the provider account associated with the configured API key, then retry. Existing versions and your conversation remain available. |
| Build fails | Check app.json, the lockfile, build script, dependencies, and service entry. The live App remains unchanged. |
| A change is not shown | Refresh, then select Build to use the latest default-branch commit. |
| Preview or Publish is unavailable | Select Preview, or choose a Ready build from Commits > Versions. Publishing has its own permission and is hidden when the selected version is already live. |
| Preview has expired or could not load | Select Retry preview to start it again. The selected version and your conversation are preserved. |
| Custom domain stays in Pending verification | Confirm the TXT record is at _knowi-verify.<domain> with the exact value shown under Custom domain, wait for DNS propagation, then select Verify again. Changing the domain issues a new token. |
| Custom domain shows a certificate warning | Confirm the CNAME (or ALIAS/ANAME for a root domain) points to domains.apps.knowi.com. The certificate is issued within a minute or two of verification. |
| Error includes "Custom domains are not enabled on this runtime" | On-premises only; raised when a live App is republished on the domain. The domain stays in Pending verification and the App keeps publishing normally on its Knowi URL. Ask a Knowi administrator to configure the Knowi Apps runtime with a certificate issuer (KNOWI_APPS_K8S_CUSTOM_DOMAIN_ISSUER), then select Verify again. |
| An image is rejected on upload | Design references accept PNG, JPEG, or WebP up to 4 MB; brand assets also accept SVG but cap at 1 MB. The extension must match the real image type, a PNG must be within 4,096 px per side and 12 megapixels, and an SVG must contain no script, event attributes, javascript: URL, or <foreignObject>. |
| No room for another image | An App holds up to 12 unused images totaling 24 MB. Remove one that no generation has used, or generate to consume the ones already attached. |
| A design reference cannot be removed | A generated version already uses it. It stays listed; its bytes were discarded when that version was created. |
| The App still shows an old logo | Brand assets stay in the repository. Attach the replacement as a brand asset and name it in the change so the App uses the new /assets/<name> URL. For a Knowi sign-in App, set branding.logo to the repository path, such as web/assets/<name>. |
| Knowi sign-in required is greyed out | App sign-in is not enabled for the deployment. Ask a Knowi administrator. |
| Sign-in branding does not appear | Branding applies only to Knowi sign-in Apps and only from the published version's app.json. Confirm the build succeeded and republish after changing it. |
| Storage change does nothing | On an existing App, after choosing the storage option under App settings > Database, select Provision Database (for Managed PostgreSQL) or Save (for No database). |
| Restore is disabled or missing | Restore is available only while the App has no published version. If there is no Restore button, the database is not Ready or the operator has not enabled restore. |
| A restore failed after the data was replaced | Do not publish until it is resolved. Restore the backup taken just before the restore from the list, or contact Knowi Support. |
| An App is missing from the list | Apps appear only for their owner and for users they are shared with, administrators included. Ask the owner to share it. |
| View as… is missing | You need account admin rights or the user:login-as permission. |
| View as… is disabled | The App must be live and use Knowi sign-in. Hover over the button for the reason. |
| View as shows App login as denied | Open the App again from the View as dialog. Its confirmation lasts 2 minutes, and a copied link cannot start a View as session. The selected user must be active in your account. |
| The Open live button asks you to sign in | The live button signs in like any visitor. To go straight in as yourself, choose View as… > You > Open as yourself. |
| An embedded App shows a blank frame or is refused by the browser | Confirm Embedding is on and that the exact site is in the allowed list. The App must use Knowi sign-in required or Public access. If the panel reports an older runtime, select Republish. If you use onError, a timeout reason means the frame never loaded. |
| An embedded App shows "could not verify your sign-in" | The single sign-on token was expired, invalid, or already used for a dashboard sign-in when single-use tokens are enforced, or the user has no access to the App. Mint a fresh token and render again. Repeated failures are temporarily throttled. |
An embedded App shows a link to open it in a new tab, or onError reports storage-blocked
|
The browser blocks the session cookie for an App on a different domain than your page, as Safari does. Serve the App from a custom domain under your own domain, or have viewers open it in its own tab. Do not render again in a loop. |
| Embedding says to republish the App | The published version uses an older runtime. Select Republish to update it. On a current runtime, embedding settings apply when saved. |
| Embedding is missing or says it is not available | The panel appears only on an existing App, for users with edit and publish permission. It is not available for App manages access Apps. |
| A Knowi dashboard does not show in an embedded App | Dashboards inside an App do not display while the App is embedded in another site. Open the App directly to see them. |
| AI edit conflicts | Refresh and request the change again from the latest version. |
| Generation fails | Read the safe failure reason shown with the job. Correct the request or source-contract issue, then retry the failed change when it is marked retryable. |
| A governed data call fails | Confirm that the exact binding key is declared in this version's app.json, the asset still exists, and the editor or publisher still has access. Rebuild and publish after changing the manifest. |
| The Git host is unavailable | The live App keeps running. Restore the connection before starting another edit or build. |
knowi_app is missing |
Verify Knowi Apps enablement, MCP authorization, and your Knowi Apps permissions. |
| Cannot create another App | Your account has reached its Knowi Apps limit. Contact your Knowi account representative. |
For help, contact Knowi Support with the App name, repository name, short commit, build state, and error message. Do not include secrets or customer data.