# Agent Observability
Source: https://docs.upsolve.ai/ai-agent-builder/agent-observability
Inspect the step-by-step trace of how your agent answered a question, and the evaluations that graded it.
Every answer your agent produces is the result of a sequence of steps: retrieving schema, looking up golden examples, generating SQL, executing it, building a chart, and writing the narrative. Agent Observability gives you the full trace of that process — plus the automated evaluations that graded the result — so you can see exactly why an answer came out the way it did.
## Reaching a trace
**From a live chat** — after the agent responds, click **Observability →** beneath the answer. The trace opens in the right-hand panel and follows the conversation as it continues.
**From Chat History** — open [Chat History](/ai-agent-builder/chat-history), click a row, and switch the sidebar to the **Observability** tab. This works for every conversation, including deployed end-user chats and MCP calls. The tab is hidden for conversations that made no tool calls, because there is nothing to trace.
## What the trace shows
### The summary bar
At the top of the trace, a row of chips summarises the whole conversation:
* **steps** — total number of tool calls the agent made.
* **duration** — total time spent inside those calls, in milliseconds.
* **rag** — how many golden queries and golden charts were retrieved as references.
* **evals** — how many automated evaluations ran. The chip is green when all of them passed and amber when any did not.
* **errors** — present only when at least one step failed.
**Expand** and **Collapse** open or close every step at once.
### Per-exchange sections
Below the summary, the trace is broken into one section per user question, each with up to four blocks:
**User Query** — the question as the user asked it.
**Agent Pipeline** — the ordered list of steps the agent took. Every step shows its own duration and success/error state, and expands to reveal its inputs and outputs. The steps you'll see include:
| Step | What it did |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Schema Retrieval** | Searched the data model for the tables and columns relevant to the question. |
| **Selectable Values** | Searched actual column values, so a filter on a category name resolves to a value that exists. |
| **Full Schema** | Loaded the whole data model — used for "what data do I have?" style questions. |
| **Golden Examples** | Retrieved confirmed question → SQL → chart pairs to use as references. |
| **SQL Generation** | Wrote the query. Shows the task it was given, the schema it was handed, the golden references it used, and the SQL it produced. If a number is wrong, start here. |
| **SQL Validation** | Checked the query against the database before running it for real. |
| **Data Retrieval** / **SQL Execution** | Ran the query and returned rows. Shows the row count and the columns that came back. |
| **Chart Generation** / **Render Chart** / **Chart Validation** | Chose the chart type, axis mappings and formatting. If the visualization is wrong but the numbers are right, the config here tells you what the agent picked. |
| **Knowledge Base Search** / **Knowledge Base File** | Searched or read a [Knowledge Base](/ai-agent-builder/knowledge-base) document. |
| **Skill** / **Skill Search** / **Skill Read** | Loaded a [Skill](/ai-agent-builder/skills) on demand. Internal plumbing skills are hidden; your own and learned skills are shown. |
| **Report Generation** / **Shareable Report** | Produced a CSV/PDF export or a shareable analysis. |
| **Suggestions** | Generated the follow-up questions offered under the answer. |
| **Learning Signal** | Recorded a correction the agent detected — the stage that went wrong, the failing artifact, and the user's correction. |
Tools you connected through [MCP](/ai-agent-builder/mcp-context) appear here too, under their own names.
**RAG Sources** — wherever a step used golden assets, the trace lists them as cards showing the retrieved question, its SQL, and a preview of its chart, each with the similarity score that earned it a place. When a trace shows the agent leaning on a bad example, the card names the [Golden Asset](/ai-agent-builder/golden-assets) to go and fix.
**Agent Response** — the narrative the user actually read.
**Evaluations** — the automated grades for this exchange. See below.
## Evaluations
Upsolve runs continuous, LLM-based evaluations against production traces. They run automatically in the background — you don't trigger them, and they don't slow the agent's answer down — and their verdicts flow back into the **Evals** column in [Chat History](/ai-agent-builder/chat-history) and into the **Evaluations** block of the trace.
### Reading a verdict
Each evaluation resolves to one of three states:
* **Pass** — the evaluation's criterion was met.
* **Fail** — the criterion was not met, or the evaluation itself errored.
* **Pending** — the evaluation hasn't returned a verdict yet. Evaluations run asynchronously, so a very recent conversation will often show pending for a short while.
The row-level verdict in Chat History is the worst state present: any failure makes the row fail, otherwise any pass makes it pass, otherwise it's pending. Hover the pill for the per-evaluation breakdown.
Expand an evaluation in the trace to see:
* **Score** — the numeric grade the evaluator returned, when it produced one.
* **Description** — what this evaluation checks.
* **Annotation** — the evaluator's written reasoning for the verdict it gave. This is the part worth reading: it usually names the specific thing that went wrong.
### What gets evaluated
Evaluations fall into two broad families. The exact set is configured per deployment, so talk to your Upsolve contact to add one or tune an existing one for your agent.
**Answer quality** — did the agent actually answer the question, and is the answer right? *Answer Correctness Judge* is the workhorse here: it grades the response against the question that was asked and the data the agent retrieved to answer it.
**Conversation health** — how the exchange is going across turns, rather than within a single answer. *Multi-Turn Forgetfulness Detector* catches the agent losing context established earlier in the conversation — a filter the user set three turns ago that silently stopped being applied. *User Frustration Detector* catches the user re-asking, correcting, or pushing back, which is the earliest reliable signal that something is wrong even when no step errored and no thumbs down was given.
Conversation-health evaluations read the whole thread, so they only produce a meaningful verdict once a conversation has enough turns. A single-question session will typically show them as not applicable rather than pass or fail.
Some evaluations run purely for Upsolve's own quality monitoring and are deliberately not surfaced in the trace, so the count in the **evals** chip can be lower than the number of evaluations that actually ran.
## Using traces to improve your agent
Observability earns its keep when an answer is wrong. The common patterns:
**Wrong SQL, right-sounding answer** — the agent generated plausible SQL that doesn't implement your business logic. Open **SQL Generation** and read the query. The fix is usually a more precise [System Prompt](/ai-agent-builder/system-prompts) rule, or a [Golden Query](/ai-agent-builder/golden-assets) demonstrating the correct approach.
**No RAG sources retrieved for a common question** — the agent answered from scratch instead of referencing a validated example. Check whether a Golden Query covers this pattern, and whether the phrasing is semantically close enough to trigger retrieval.
**The wrong golden asset was retrieved** — the trace shows a RAG source that doesn't fit the question. Note which asset the card names, then sharpen its question text in [Golden Assets](/ai-agent-builder/golden-assets), or retire it.
**Correct SQL, wrong chart** — the data was right but the visualization misled. Add a [Golden Chart](/ai-agent-builder/golden-assets) for this question type.
**Errors in the pipeline** — a red step names the failure directly. A failed SQL execution usually points at a data model that promises a column the warehouse doesn't have; a failed validation usually points at generated SQL the dialect rejects.
**High cost or many steps** — the trace shows repeated SQL attempts before a correct result. That normally means the data model annotations or system prompt need more specificity, so the agent stops guessing.
**A thumbs down with no obvious error** — read the **Annotation** on the failing evaluation, then the **Agent Response** block. Framing problems (over-claiming, missing caveats, too much jargon) don't surface as errors anywhere else.
## Next steps
Browse conversations as sessions or traces, and filter on evals, feedback, errors and cost.
Add example queries and charts to fix patterns you identify in traces.
# Agents
Source: https://docs.upsolve.ai/ai-agent-builder/agents
Build AI chat experiences that understand your data.
## What is an Agent?
An Agent is an AI-powered chat interface that:
* Converts natural language questions into SQL
* Analyzes results and provides insights
* Creates visualizations from query results
* Learns from examples (Golden Assets)
## Agent Components
### Data Model Link
Every agent is linked to a specific data model version. This ensures:
* The agent knows what tables and columns exist
* Changes to the data model don't break the agent
* You can test with different data model versions
### System Prompt
A custom prompt that shapes how the agent responds:
* Company context and terminology
* Response style preferences
* Special instructions
### Golden Assets
Example queries and charts that teach the agent:
* How to write SQL for common questions
* What visualizations to create
* Correct terminology and calculations
### Evaluations (Evals)
Test sets to verify agent accuracy:
* Known question-answer pairs
* SQL validation
* Result comparison
## Creating an Agent
1. Navigate to your project's **Agents** tab
2. Click **Create Agent**
3. Enter a name and description
4. Select the data model to use
5. Click **Create**
## Configuring Your Agent
### Setting the System Prompt
1. Open your agent
2. Go to the **System Prompt** tab in the sidebar
3. Write instructions for the agent
4. Click **Save**
Example system prompt:
```
You are a data analyst for an e-commerce company.
Use clear, business-friendly language.
When users ask about "revenue," they mean gross_sales minus refunds.
Always include date ranges in your analysis.
```
### Adding Golden Assets
Golden Assets are example queries that improve accuracy:
1. Go to the **Assets** tab
2. Click **Add Asset**
3. Enter the question and corresponding SQL
4. Optionally add a chart configuration
5. Click **Save**
**Tip:** The more golden assets you add for common questions, the more consistent your agent becomes.
### Creating Evaluations
1. Go to the **Tests** tab
2. Click **Add Test**
3. Enter a question
4. Enter the expected SQL or answer
5. Save and run the test
## Admin View vs User View
### Admin View
As an admin, you see full details:
* Every tool call the AI makes
* SQL queries generated
* Step-by-step reasoning
* Token usage and timing
### User View
End users see a clean interface:
* Just the question and answer
* Charts and insights
* No technical details
## Versioning
Like data models, agents are versioned:
1. Go to the **Versions** tab
2. See all versions with timestamps
3. Each version tracks: assets, prompt, data model link
## Setting Production
Before users can access your agent, you must set a version as production.
### Requirements
1. The agent must be linked to a data model
2. That data model version must already be production
3. The agent's schema requirements must fit within the data model
### Steps
1. Open your agent
2. Go to the **Versions** tab
3. Click **Set as Production** on the version you want
4. The system validates everything
5. If successful, users can now access this version
### Validation Errors
If validation fails, you'll see specific errors:
* "Data model version is not production" - Set the data model production first
* "Missing tables/columns" - The agent uses data not in the data model
## Changing Data Model Version
To link your agent to a different data model version:
1. Go to the **Data Model** tab in the sidebar
2. Select the data model
3. Choose a version (production versions recommended)
4. Click **Save**
This creates a new agent version with the new data model link.
## Best Practices
### 1. Start with Golden Assets
Add 10-20 golden assets covering common questions before going live.
### 2. Use Descriptive Data Models
Column descriptions in your data model help the agent understand your schema.
### 3. Run Evals Regularly
Create a test suite and run it whenever you update the agent.
### 4. Monitor in Admin View
Periodically check admin view to see how the agent handles real questions.
## Next Steps
* [Build an Application](/ai-agent-builder/applications) to combine agents with dashboards
* [Set up the complete flow](/ai-agent-builder/setup-guide) from project to production
# Applications & Spaces
Source: https://docs.upsolve.ai/ai-agent-builder/applications
Build dashboard templates and deploy them to customer spaces.
## What is an Application?
An Application is a container for dashboard templates that you deploy to your customers. It includes:
* **Chart Templates** - Reusable chart configurations
* **Dashboard Templates** - Layouts combining multiple charts
* **Spaces** - Customer-specific instances of your templates
* **Default Settings** - Language, timezone, export options
## How Applications and Spaces Work
```mermaid theme={null}
flowchart TD
A[Application] --> B[Chart Templates]
A --> C[Dashboard Templates]
A --> D[Spaces]
D --> E[Space for Org 1]
D --> F[Space for Org 2]
D --> G[Space for Org 3]
```
Each space receives its own private copies of your published templates.
When you publish a template:
1. It becomes available to all spaces
2. Each space gets its own private copy
3. Users can customize their copies without affecting others
## Creating an Application
1. Navigate to your project's **Applications** tab
2. Click **Create Application**
3. Enter a name
4. Select a data model
5. Click **Create**
## Building Templates
### Creating a Chart Template
1. Open your application
2. Click **Add Chart**
3. Choose a chart type
4. Configure the data and visualization
5. Click **Save**
### Creating a Dashboard Template
1. Open your application
2. Click **Add Dashboard**
3. Drag and drop charts onto the canvas
4. Arrange the layout
5. Add filters if needed
6. Click **Save**
## Viewing as a User
While building templates, you see them as an admin. To see what users will see:
1. Select a project user from the dropdown
2. The view switches to their perspective
3. Data is filtered by their RLS rules
4. Check that the template works for different users
## Publishing Templates
Templates start in "draft" mode. To make them available to users:
1. Open the template
2. Click **Publish**
3. The template propagates to all spaces
### What Happens When You Publish
1. Template status changes to "published"
2. Each space gets a copy of the dashboard
3. Users can now see and interact with it
4. Future updates require re-publishing
## Understanding Spaces
Each project organization automatically gets a Space for each application.
### What's in a Space?
* **Template Copies** - Private instances of published templates
* **User Dashboards** - Dashboards users create themselves
* **User Charts** - Charts users create themselves
### Viewing Spaces
1. Open your application
2. Go to the **Spaces** tab in the sidebar
3. See all spaces (one per organization)
4. Click to preview any space
## Default Views
You can set which dashboard users see first when they open their space.
### Setting an Application Default
1. Open your application
2. Go to the **Templates** tab
3. Click the star icon next to a template
4. This becomes the default for all users
### User-Specific Defaults
Users can change their own default:
1. Open any dashboard in their space
2. Click **Set as Default**
3. This overrides the application default for them only
## Application Settings
### Default Language
Set the default language for your application:
1. Go to application settings
2. Select default language
3. Users can override in their preferences
### Default Timezone
Configure how dates are displayed:
1. Go to application settings
2. Set the default timezone offset
3. Enable "Use Local Timezone" for auto-detection
### Export Settings
Control whether users can export data:
1. Go to application settings
2. Toggle "Allow Exports"
## Production Status
Like data models and agents, applications can be set to production.
### Requirements
1. Application must have a linked data model
2. That data model version must be production
3. All template schemas must fit within the data model
### Setting Production
1. Open your application
2. Go to the **Versions** tab
3. Click **Set as Production**
4. Validation runs automatically
## Connecting Agents and Applications
If an agent and application share the same data model version:
* The agent can generate charts compatible with the application
* Users can save agent-generated charts to their space
* Charts flow seamlessly between AI and dashboards
## Best Practices
### 1. Test with Multiple Users
Always preview templates as different users to ensure RLS works correctly.
### 2. Start with Core Dashboards
Create 2-3 essential dashboards before adding more.
### 3. Use Consistent Naming
Name templates clearly so users understand what they show.
### 4. Document in Descriptions
Add descriptions to dashboards explaining what they display.
## Next Steps
* Follow the [Complete Setup Guide](/ai-agent-builder/setup-guide) for the full workflow
* Learn about [Row-Level Security](/ai-agent-builder/rls) for data filtering
# Chat History
Source: https://docs.upsolve.ai/ai-agent-builder/chat-history
Review every conversation your agent has handled, as sessions or as individual traces.
Chat History is the operational view of your agent. It lists every conversation the agent has handled — sessions run in Agent Studio, live chats from deployed end users, and calls that came in over MCP — with the quality, cost and reliability signals for each one attached to the row.
It answers two different questions, and it has a view for each:
* **Sessions** — "how is this conversation going?" One row per conversation.
* **Traces** — "how did this answer turn out?" One row per user question → agent answer exchange.
Use the **Sessions / Traces** toggle in the toolbar to switch. Both views share the same filters, column controls, time range and CSV export; only the grain changes.
## Sessions view
One row per conversation. Available columns:
| Column | What it shows |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Date** | When the conversation started. |
| **Evals** | Aggregate verdict of the automated evaluations that ran on this conversation — pass, fail, or pending. Hover for the per-eval breakdown. |
| **Summary** | A short generated description of what the conversation was about. |
| **Feedback** | The thumbs up / thumbs down the user submitted, if any. Hover to read the written comment. |
| **Charts** | How many charts the agent built. |
| **Errors** | How many steps failed — a failed SQL execution, a tool error, a rejected query. |
| **Questions** | How many questions the user asked in the conversation. |
| **RAG Sources** | How many golden queries and golden charts were retrieved as references. |
| **Cost** | Model spend for the conversation, in USD. |
| **Duration** | Wall-clock length of the session. |
| **User** | The project user who was chatting, or *Admin* for a builder session in Agent Studio. |
| **Platform** | Where the conversation came from — *Agent Studio*, *Embedded*, or *MCP*. |
**Duration**, **User** and **Platform** are hidden by default. Turn them on from the column picker.
## Traces view
One row per exchange, so a five-question conversation produces five rows. This is the grain to work at when you're triaging quality: an eval failure, a thumbs down or an error belongs to a specific answer, not to the whole session.
| Column | What it shows |
| ---------------- | ------------------------------------------------ |
| **Time** | When the exchange happened. |
| **Evals** | The evaluation verdict for this specific answer. |
| **User Input** | The question as the user asked it. |
| **Agent Output** | The answer the agent gave. |
| **Feedback** | Thumbs up / down on this answer. |
| **Charts** | Charts produced by this answer. |
| **Errors** | Failed steps within this answer. |
| **RAG Sources** | Golden assets retrieved for this answer. |
| **Cost** | Model spend attributed to this exchange. |
| **User** | Who asked. |
| **Platform** | Where the question came from. |
| **Trace ID** | The observability trace identifier. |
| **#** | The exchange's position within its conversation. |
**User**, **Platform**, **Trace ID** and **#** are hidden by default.
## Working the table
**Filters** — the chip bar on the left of the toolbar filters on any visible column: eval status, feedback, platform, user, and numeric ranges for charts, errors, questions, RAG sources and cost. Filters follow column visibility: hiding a column hides its filter but keeps the filter's value, so toggling the column back on restores it.
**Time range** — narrow to the past 5 minutes, 30 minutes, hour, day, week, month, 3 months or year. Defaults to all time.
**Columns** — the column picker lets you show and hide columns and drag them into the order you want. Columns can also be resized by dragging their edge in the header. Your choices persist per view; **Reset to defaults** in the picker restores the shipped layout.
**Reload** — re-fetch without leaving the page. Useful when you're watching a live deployment.
**Export CSV** — exports the current view with the columns you have visible, so the export matches what you're looking at.
## Opening a conversation
Click any row to open the detail sidebar.
The metadata card at the top carries **Date**, **Duration**, **Tenant**, **Agent**, **Platform**, **Cost**, the **Session ID**, and — when you opened the sidebar from a Traces row — the **Trace ID** for that exchange. Both identifiers can be copied with one click. If the user left feedback, **Feedback** and their **Comment** appear underneath.
Below the metadata card are two tabs:
* **Chat** — the conversation exactly as it happened, including the charts the agent rendered.
* **Observability** — the step-by-step trace of what the agent did. This tab only appears for conversations that actually made tool calls.
Everything here covers deployed end-user chats as well as your own Agent Studio sessions. There is nothing extra to enable — a conversation from an embedded deployment or an MCP client shows up with its **Platform** set accordingly.
## Next steps
Inspect the step-by-step trace behind any answer, and the evaluations that graded it.
Add example queries and charts to fix patterns you identify in past conversations.
# Data Model & Schema
Source: https://docs.upsolve.ai/ai-agent-builder/data-model-schema
Choose which tables and columns the agent can see, and encode what they mean.
The Data Model is the foundation of your agent's knowledge — every other entry point in this section ([System Prompts](/ai-agent-builder/system-prompts), [Golden Assets](/ai-agent-builder/golden-assets), [Skills](/ai-agent-builder/skills), [Knowledge Base](/ai-agent-builder/knowledge-base), [User Memory](/ai-agent-builder/user-memory), and [MCP](/ai-agent-builder/mcp-context)) builds on top of it. It controls two things: what data the agent can access, and what context it has to interpret that data correctly. A well-configured data model is the difference between an agent that writes plausible SQL and one that writes the *right* SQL for your business.
## Selecting tables and columns
Not every table in your database is relevant to every question your agent will answer. Narrowing the schema down to what matters reduces ambiguity, improves query accuracy, and avoids the agent making inferences across data it shouldn't touch.
From the **Tables** tab in your Data Model, select the tables you want to expose to the agent. By default all tables from your connection are listed — check only the ones that are relevant to the use case you're building for.
Within each table, you can further control which columns are included. Expand a table to see its columns, then uncheck any that are unnecessary, sensitive, or likely to confuse the agent. The column list shows the name, data type, and any description you've added.
Less is more here. An agent scoped to 5 relevant tables with clear descriptions will significantly outperform one with access to 50 tables it has to guess about.
## Adding table and column descriptions
Descriptions are how you encode institutional knowledge directly into the schema. The agent reads these when generating SQL — they're the mechanism for telling it what your data actually means, not just what it's called.
**Table descriptions** provide context for the whole table — what it represents, how it's populated, any important caveats. Click into a table and use the **Table Description** field at the top of the column panel to add this.
**Column descriptions** sit inline next to each column. Click the description field for any column and add a plain-English explanation. Useful descriptions answer the question a developer would have when first looking at the column: what does this value represent, what are the units, is there anything non-obvious about how it's calculated?
For example:
* `contact_name` → *"Name of the customer's point of contact for this order"*
* `owner_name` → *"Name of the sales rep (seller) who owns this account"*
* `arr` → *"Annual Recurring Revenue in USD, calculated as MRR × 12. Excludes one-time fees."*
The more specific your descriptions, the more reliably the agent will apply the right column to the right question.
## Marking columns as selectable
The **Selectable** toggle controls whether the agent can scan a column's distinct values at query time to inform how it builds SQL.
When a column is marked selectable, the agent can run `DISTINCT()` over it to extract its unique values, and then use those values in two ways:
* **Categorical filtering in SQL writing** — the agent knows the valid filter values *before* it writes a `WHERE` clause. It knows that `region` contains "North America", "EMEA", and "APAC", so it filters on real values rather than guessing at spellings or inventing categories.
* **Text grep search** — the agent can search across a selectable column's values to find the exact entry a user referred to loosely (e.g. matching "acme" to the `customer_name` value "Acme Corp (US)").
Think of it as giving the agent the ability to power a select-style filter: it knows the possible values and can use them precisely.
Mark a column as selectable when:
* It contains categorical values users would naturally filter by (region, product, owner, status)
* The distinct values are finite and meaningful to business questions
* You want the agent to be able to enumerate or search options rather than guess at valid values
Leave it off for high-cardinality columns (IDs, free-text fields, timestamps) where scanning distinct values would be noisy or meaningless.
## Beyond the schema: the Knowledge Base tab
The Data Model editor has three tabs — **Tables**, **Global Data Security**, and **Knowledge Base**. Descriptions on tables and columns cover what your *data* means, but some context isn't about any one column: business policies, company background, definitions of terms users use loosely, and known caveats about the data. Those live in the Knowledge Base as searchable markdown documents that ship with each data model version. See [Knowledge Base](/ai-agent-builder/knowledge-base) for how to add and organize them.
## Saving your changes
Changes to the data model create a new draft version. Click **Save Version** in the top-right corner when you're ready to checkpoint your work. A data model version must be marked as **Production** before an agent can use it in a live environment.
Agents are linked to a specific data model version. Updating the data model does not automatically update agents that reference it — you'll need to update the agent's data model link and set a new production version.
## Next steps
Encode business rules, terminology, and behavioral guardrails into the agent.
Add example queries and charts the agent can reference when answering similar questions.
Store reference documents the agent searches on demand to interpret your terms.
Package procedures and conventions the agent loads when it needs them.
Let the agent record and apply each end user's preferences automatically.
Connect external tools and live systems as additional agent context.
# Data Models
Source: https://docs.upsolve.ai/ai-agent-builder/data-models
Create curated views of your database with descriptions, annotations, and versioning.
## What is a Data Model?
A Data Model is a curated view of your database that:
* **Selects** which tables and columns are available
* **Describes** fields with human-readable annotations
* **Secures** data with row-level security rules
* **Versions** changes so you can track and rollback
## Why Use Data Models?
1. **Simplify for AI** - Only expose relevant tables so AI agents aren't overwhelmed
2. **Add context** - Descriptions help AI understand what columns mean
3. **Control access** - Data Security rules ensure users see only their data
4. **Safe deployments** - Versioning prevents breaking changes
## Creating a Data Model
1. Navigate to your project's **Data Models** tab
2. Click **Create Data Model**
3. Select the connection to base it on
4. Enter a name for your data model
5. Click **Create**
The system will fetch all tables and columns from your connection automatically.
## Configuring Your Data Model
### Selecting Tables and Columns
By default, all tables are selected. To customize:
1. Open your data model
2. Uncheck tables you want to hide
3. Expand tables to uncheck specific columns
4. Click **Save Changes**
### Adding Descriptions
Help AI and users understand your data:
1. Click the edit icon next to a table or column
2. Enter a description
3. For AI agents, mark columns as "selectable" if they contain categorical values users might filter by
## Data Security
Data Security controls which rows of data each user can access. You can define **Global Security Rules** that apply across all tables, or configure per-table rules for specific needs.
### Understanding Data Security
The Data Security system uses SQL-based filtering with dynamic variables:
* **`{{user.*}}`** - Access properties of the currently authenticated user
* **`{{organization.*}}`** - Access properties of the user's organization
For example, to filter an `orders` table so users only see their own orders:
```sql theme={null}
SELECT *
FROM "orders"
WHERE "user_id" = '{{user.id}}'
```
### Global Security Rules
Global Security Rules let you define filtering logic once and apply it to all applicable tables automatically. This is ideal when you have consistent patterns like:
* Multi-tenant data separated by `tenant_id`
* User-owned data filtered by `user_id`
* Schema-based isolation (each tenant has their own database schema)
#### Accessing Global Rules
1. Open your data model
2. Click the **Global Data Security** tab, alongside **Tables** and **Knowledge Base**
3. You'll see the Global Rules editor, with **+ Add Rule** above any rules that already exist
#### Rule Types
**Schema Rules** - Dynamic schema prefixing for multi-tenant databases where each tenant has their own schema:
This generates SQL like:
```sql theme={null}
SELECT *
FROM "{{user.schema}}"."orders"
```
**Column Rules** - Automatic WHERE clause filtering based on column names:
This generates SQL like:
```sql theme={null}
SELECT *
FROM "orders"
WHERE "user_id" = '{{user.id}}'
```
#### Creating a Global Rule
1. Click the **Global Data Security** tab
2. Click **Add Rule**
3. Choose **Schema Rule** or **Column Rule**
4. Configure the rule settings
5. The rule is automatically enabled
#### How Rules Are Applied
* **Schema rules** affect all tables - they change where data is fetched from
* **Column rules** only affect tables that have the specified column - tables without the column are unaffected
* Multiple rules are combined with AND logic
* Rules are applied in priority order (lower priority number = applied first)
Applying the rules opens a preview first: the SQL each table will be given, a count of how many will be filtered, and — because a manual override always wins — how many will be skipped.
### Per-Table Data Security
Selecting a table under **Tables** gives it its own **Data Security** sub-tab — distinct from the model-wide **Global Data Security** tab — showing how the global rules apply to that one table.
#### Manual Overrides (Break Glass)
Sometimes you need custom logic for a specific table. You can override global rules:
1. Select the table under **Tables**
2. Go to its **Data Security** sub-tab
3. Click **Edit manually**
4. Confirm the warning dialog
5. Edit the SQL directly
Once in manual mode, you have full control over the SQL:
#### Resetting to Global Rules
To return a table to global rule management:
1. Click **Reset to global**
2. Confirm the dialog
3. Your manual edits will be replaced with the auto-generated SQL
### Testing Data Security
You can test your security rules to see exactly what data a specific user would see:
1. Select a table under **Tables**
2. Go to its **Data Security** sub-tab
3. Select a user from the top-right user dropdown
4. Click **Test Query**
5. View the filtered results
Testing uses your actual database connection and shows real data filtered by the security rules. This helps verify your configuration before deploying.
## Versioning
Every change to a data model creates a new version. This means:
* You can see the history of changes
* You can compare versions
* Agents and applications link to specific versions
### Viewing Versions
1. Open your data model
2. Click the **Versions** tab in the sidebar
3. See all versions with timestamps and change information
## Production Status
Before agents and applications can use a data model in production, you must mark a version as "Production."
### Setting Production
1. Open your data model
2. Go to the **Versions** tab
3. Click **Set as Production** on the version you want
4. The system validates the schema against your connection
5. If successful, the version is now production
### Validation
When setting production, the system checks:
* All tables in your data model exist in the connection
* All columns in your data model exist in their tables
* If validation fails, you'll see which tables/columns are missing
If your database schema changes, you may need to update your data model to match.
## Syncing with Connection Changes
If your database schema changes:
1. Open your data model
2. Go to the **Connection** tab
3. Click **Refresh Schema**
4. New tables/columns will appear (you can select them)
5. Missing tables/columns will show warnings
## Data Model Errors
If a production data model has errors (e.g., missing tables), you'll see a warning banner. This typically happens when:
* A table was dropped from the database
* A column was renamed or removed
* The connection credentials changed
## Next Steps
* [Create an Agent](/ai-agent-builder/agents) that uses this data model
* [Build an Application](/ai-agent-builder/applications) for dashboards
* [Manage Project Users](/ai-agent-builder/users) to define user properties for Data Security
# Backend Setup
Source: https://docs.upsolve.ai/ai-agent-builder/deploy-agents/backend-setup
Set up user authorization in the backend for agent deployment
## User Authorization
The purpose of user authorization set up in the backend is for Upsolve AI to provide appropriate data access based on your user permissioning set up.
In your product's authentication flow, you register users with Upsolve using the [project user registration flow](/embedded-bi/data-permissioning/project-user-registration-flow): register an [organization](/api-reference/endpoint/register-project-organization) once per customer entity, register a [user](/api-reference/endpoint/register-project-user) once per account, then fetch a short-lived [user token](/api-reference/endpoint/get-project-user-token) on every login. The token tells Upsolve AI who the authorized user is and what data they can access, and is used to provide the appropriate access to the agent and underlying data.
To generate your API Key please go to the deploy page.
## Project User Token
When embedding an Application Space (via the `https://ai-hub.upsolve.ai/share/application/:applicationId` iFrame), you need a **project user token**. This token identifies a specific user within a project organisation and is used by the embed to load their personalised Space.
### Endpoint
```
POST https://api.upsolve.ai/v1/api/projects/user-token
```
### Request
| Field | Type | Required | Description |
| ---------------- | ------------- | -------- | --------------------------------------------------------------------- |
| `userId` | string (UUID) | Yes | The project user's ID (found in your project's user list) |
| `organizationId` | string (UUID) | Yes | The organisation ID the user belongs to |
| `apiKey` | string | No | Your Upsolve embed API key (if not passed via `Authorization` header) |
| `expiration` | number | No | Token lifetime in seconds (default: 3600) |
### Response
```json theme={null}
{
"data": {
"token": ""
}
}
```
### Example
```typescript theme={null}
const response = await fetch("https://api.upsolve.ai/v1/api/projects/user-token", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer up_embed_...", // Your embed API key
},
body: JSON.stringify({
userId: "user-uuid-here",
organizationId: "org-uuid-here",
}),
});
const { data } = await response.json();
const projectUserToken = data.token;
```
Pass `projectUserToken` as the `jwt` query parameter in the Application iFrame `src`. See [Frontend Setup](/ai-agent-builder/deploy-agents/frontend-setup) for the full embed example.
Project user tokens expire after 1 hour by default. Refresh them server-side before they expire and update the iFrame `src` to avoid session interruptions.
New integrations should use `POST /v1/api/projects/user-token` directly. Legacy tenant-based integrations remain supported, but the project user flow is the recommended path going forward.
## Setup Inspection
You could inspect whether the user authorization is setup successfully. Navigate to the **Deploy** application using the side navigation bar.
If the endpoint is successfully called, you should see your new tenants in the **Deploy** application:
# Canvas Iframe Embed
Source: https://docs.upsolve.ai/ai-agent-builder/deploy-agents/canvas-iframe-embed
Embed a public canvas into your product with an iframe
## Overview
You can embed a public Agent Canvas into your own product using a standard HTML `