# Skills & the AI widget (/docs/analytical-apps/skills)



A **skill** is a reusable, app-specific AI task that you author once and offer to
other people as a one-click action. The motivating example is an emission-factor
app: a user types a material description, and the skill walks the factor taxonomy
and returns the best-matching factor with its value and source. Other apps have
other skills.

Skills are first-class parts of your app, managed on the **Skills** tab of the
[Knowledge Base](./knowledge-base.mdx) panel and versioned, drafted, and published
together with everything else in the app. One definition reaches two audiences:

* **In-app end users** run a skill from an **AI widget** on the Visualisation
  canvas and read the answer inline.
* **External AI clients** (your own AI connected to your workspace) can invoke the
  same skill as an **MCP prompt**.

## What a skill is made of [#what-a-skill-is-made-of]

A skill carries a little structured metadata on top of a markdown body:

* **Name** - the display name shown as the widget title and in pickers.
* **Technical ID** - a stable, lowercase id (for example `find_emission_factor`).
  It is fixed once the skill is created, because the widget and the MCP prompt both
  refer to the skill by it. The display name stays editable; to change the
  technical id itself, delete the skill and create a new one.
* **Description** - a one-line summary shown under the widget and to external AI
  clients.
* **Inputs** - the questions the skill asks the user. Each input has a label (what
  the user sees), an argument key (a lowercase id), an optional helper text, and a
  required flag. A skill can have zero inputs (just a Run button) or several.
* **Expose as an MCP prompt** - on by default; turn it off to keep a skill in-app
  only.
* **Instructions** - the body, written in plain language in the same rich text
  editor as Knowledge Base pages and stored as markdown. This is the task you are
  giving the AI ("You help the user map a material to an emission factor. Filter
  by domain, then activity, and return the single best match with its factor
  value and source.").

## Authoring a skill [#authoring-a-skill]

Open your analytical app in the editor, open the **Knowledge Base** panel, and
switch to its **Skills** tab. The left rail lists the app's skills; the right side
is the editor.

1. Click the add button to start a new skill.
2. Type a **name**. The technical id is suggested from the name; you can adjust it
   while creating, but it is fixed afterwards.
3. Write a short **description**.
4. Add the **inputs** the skill needs, one row each. Mark the ones that must be
   filled in as required.
5. Decide whether to **expose it as an MCP prompt**.
6. Write the **instructions** in the body editor.
7. Save.

Skills are part of your app configuration, so they are edited on a draft and become
available to end users and external AI clients when you **publish** the app. When
you pin a past version in the app's history, the Skills section shows that
version's skills read-only. See
[Draft and publish](../overview/apps.mdx#draft-and-publish).

## Adding an AI widget [#adding-an-ai-widget]

An AI widget lets end users run a skill from a Visualisation.

1. Open the **Visualisation** section and add an **AI** widget from the palette.
2. In the widget settings, pick the **skill** it should run. The widget title
   defaults to the skill's name; you can override it.
3. Publish the app so your viewers see the widget.

On the published Visualisation the widget shows one field per skill input and a
**Run** button. A short line under the button tells the viewer how long a run may
take: a skill is **bounded to about 30 steps and about 150 seconds**, so it always
finishes promptly rather than spinning.

Running the widget is **read-only**. Vera reads existing configuration and queries
published data to answer. It cannot edit data, change the pipeline or Knowledge
Base, publish, or create a draft, even when the user has editing permissions.
Previewing a skill reads an existing draft without changing it. If a task needs
a change, Vera explains briefly that the widget cannot make it. Widget answers
are separate from the user's conversation in the editor's Vera panel.

### What the viewer sees while it runs [#what-the-viewer-sees-while-it-runs]

While the skill runs the widget stays transparent. It shows:

* the **current action** Vera is taking (for example "Querying the data" or
  "Inspecting the node columns"),
* an **elapsed timer** counting up from the start, and
* a **live step trace** - the sequence of actions Vera has taken so far, including
  the SQL queries it runs against your data.

This means a viewer can see, at a glance, what is happening and roughly how far
along the run is.

### The result [#the-result]

When the run finishes the widget leads with **the answer*&#x2A;, rendered as formatted
text. Below the answer a collapsible &#x2A;*"How Vera got this"** section reveals the
full step trace and a subtle line showing the AI credits the run used, so a viewer
can check how the answer was reached.

The widget makes each outcome distinct:

* **Answer ready** - the answer is shown, with the "How Vera got this" trace
  available and a **Run again** action.
* **No answer** - the run finished but Vera did not produce a result. The widget
  says so plainly and offers **Try again**. It never falls back to unrelated text.
* **Ran out of steps** - the run reached its step or time limit before finishing.
  The widget shows the partial result, notes that it was cut short, and offers
  **Try again** (try a more specific request).
* **Error** - something went wrong; the message is shown with **Try again**.

If the assistant needs more information it asks a follow-up question right in the
widget, and the person who started the run answers to continue.

Running a skill uses AI, so the person running it needs AI access on the app. Every
role but **Viewer** has it. Someone with the **Viewer** role sees the widget's inputs
disabled and a line saying that running it needs AI access, with no **Run** button. If
their access could not be checked (for example on a connection problem), the line says so
instead. An administrator can also switch a person's AI off in their **AI permissions**;
the widget then explains that AI is not enabled for them.

## Skills as MCP prompts [#skills-as-mcp-prompts]

Every published skill that has **Expose as an MCP prompt** turned on is available
to your own AI over your workspace's MCP connection as a prompt named
`{app_technical_id}.{skill_technical_id}` (for example
`emission_factor_hub.find_emission_factor`). The skill's inputs become the prompt's
arguments. Your AI client fetches the prompt, fills in the arguments, and runs it
against the tools your workspace exposes. Skills that are still on a draft, or that
have the toggle turned off, are not offered as prompts.

A skill's instructions are your workspace's own content, so the prompts are covered by the
same AI privileges as everything else: the connection needs **List skills** to see them and
**Get skill** to fetch one. Both are part of the standard read permissions. If a connected AI
reports no prompts even though you have published skills with the toggle on, that connection
is missing those two - a workspace admin can add them on the **AI privileges** settings for
that person, and the prompts appear on the next request without reconnecting.

## Built-in prompts [#built-in-prompts]

Beyond skills you publish yourself, your workspace's MCP connection also offers five
ready-made prompts covering common tasks, available on every workspace: `create-node`
(create a pipeline node on an app's draft), `run-pipeline` (run an app's pipeline and
report the result), `query-data` (answer a data question over an app's data with SQL),
`collect-indicator-values` (walk through entering missing indicator values for an open
reporting period), and `report-status` (summarise reporting-period completion for an
indicator app). Each asks for anything it needs, such as which app, if you have not
said already.

Each of these needs its own AI privileges to appear, the same as a tool: your AI
client only sees the ones your effective permissions cover, whether or not you have
published any skills of your own.

See [Connect your own AI](../integrations/mcp.mdx) for how to connect an external
AI client to your workspace.
