--- title: "KlicForge documentation" url: "/" description: "Build, configure and operate AI agents for your business — guides for everyone from first-time users to developers integrating KlicForge." productArea: getting-started audience: ["business-user", "developer", "admin"] tags: ["overview"] lastReviewed: 2026-07-28 --- # KlicForge documentation (/) KlicForge lets you build AI agents that answer questions, capture information and take actions across chat channels — configured from a dashboard, without writing code. ## What do you want to do? [#what-do-you-want-to-do] Build, ground, test and publish your first agent. Put your agent on your website, Telegram or WhatsApp. Embed the widget SDK, connect your own tools, or wire up an MCP server. Members and roles, plans, usage and security. Work through common problems by symptom. How KlicForge counts interactions against your plan. ## The core ideas [#the-core-ideas] An **[agent](/agents)** is the unit you build and deploy. It combines: * **[Knowledge sources](/knowledge)** — your content, so it answers from your material rather than guesswork. * **[Skills](/skills-and-tools)** — instruction modules shaping how it behaves. * **[Tools](/skills-and-tools/tools)** — functions it can call to look things up and take actions. * **[Data tables](/data-tables)** — structured storage it can read and write during a conversation. * **[Guardrails](/guardrails)** — safety controls enforced by the runtime, not just requested in a prompt. You then put it in front of people on a **[channel](/channels)**, test it with **[evaluations](/evaluations)**, and let it reach out with **[scheduled tasks](/scheduled-tasks)**. ## New here? [#new-here] Start with the [quickstart](/getting-started) for the short version, or [create your first agent](/getting-started/create-your-first-agent) for a full walkthrough. Unsure what a word means? The [glossary](/reference/glossary) lists KlicForge's terms alongside the names they are commonly called elsewhere. --- title: "Core prompt files" url: "/agents/core-prompt-files" description: "IDENTITY, SOUL, AGENTS and USER — the four files that define how an agent behaves, and how to write each one." productArea: agents audience: ["business-user", "developer"] tags: ["agents", "prompts"] lastReviewed: 2026-07-30 --- # Core prompt files (/agents/core-prompt-files) An agent's behaviour is defined by four Markdown files, edited on the agent's **System Prompt** tab. Each has a distinct job. Keeping them separate is what makes an agent's behaviour predictable and easy to change. All four are optional, but an agent with none of them written will behave generically. ## The four files [#the-four-files] | File | Answers the question | Typical length | | ------------ | --------------------------------------- | -------------- | | **IDENTITY** | Who is this agent? | 10–30 lines | | **SOUL** | How does it speak? | 5–20 lines | | **AGENTS** | What can it do, and what can it not do? | 10–30 lines | | **USER** | Who is it talking to? | 5–15 lines | ## IDENTITY [#identity] Role, purpose and core capabilities. This is the agent's job description. Write: * Who the agent works for, by name * What it is for, in one sentence * The boundaries of its role * What it should do when a request falls outside that role Avoid putting tone here — that belongs in SOUL. ```markdown # Identity You are the support assistant for Northwind Coffee, an online coffee subscription service. Your role is to answer customer questions about orders, subscriptions, delivery and returns using the Northwind knowledge base. You do not give advice on payment disputes, and you never process refunds yourself — you collect the details and hand off to a human. ``` ## SOUL [#soul] Personality, tone and interaction style. Nothing about capability. ```markdown # Soul Warm, brief and practical. Write like a knowledgeable colleague, not a brochure. Prefer short paragraphs. Use the customer's name if you know it. Never use exclamation marks more than once in a reply. When you have to deliver bad news, lead with what you can do. ``` Tone belongs in SOUL, not in a skill. Adding a skill to adjust tone makes behaviour harder to predict because skill instructions compose with everything else. SOUL written by the creation wizard includes a `## Your Point of View` section for customer-facing agents, stating the voice in the agent's own words: ```markdown ## Your Point of View You speak as part of the practice, not about it. Our packages, our therapists, our availability. ``` This is ordinary SOUL content — edit or remove it like anything else. It is separate from the **point of view** setting on the Communication Style card, which applies its own instruction at every turn. Setting both is fine; they say the same thing. ## AGENTS [#agents] An explicit list of what the agent can and cannot do. This is what stops it inventing capabilities. ```markdown # Capabilities You can: - Look up order status using the order lookup tool - Explain delivery timelines and the returns policy from the knowledge base - Capture a callback request into the support table You cannot: - Change or cancel an order - Issue a refund - Access payment card details ``` Be concrete. "You cannot access payment details" prevents a class of bad answers that "be careful with sensitive data" does not. ## USER [#user] Who the agent is talking to, so it can pitch its answers correctly. ```markdown # Audience Existing subscribers, mostly non-technical, usually on a phone. Many are mid-purchase and impatient. Assume no knowledge of internal terminology. Do not use words like "SKU" or "fulfilment partner" — say "product" and "delivery company". ``` ## How they combine [#how-they-combine] At runtime the four files are composed into the agent's instructions, alongside any attached [skills](/skills-and-tools), the [guardrail](/guardrails) rules, and retrieved [knowledge](/knowledge). Keeping each file to its own concern means you can change tone without touching capability, and vice versa. ## Writing well [#writing-well] * **Be specific.** Vague instructions produce inconsistent behaviour. * **Write rules, not essays.** The agent follows short, clear statements more reliably. * **Say what to do, not only what to avoid.** "Hand off to a human" beats "don't answer". * **Test after each change.** Use the agent's **Sandbox** tab, or [evaluations](/evaluations) to catch regressions automatically. ## Related pages [#related-pages] * [Agents overview](/agents) * [Guardrails](/guardrails) * [Evaluations](/evaluations) --- title: "Agent creation wizard" url: "/agents/creation-wizard" description: "The three routes for creating an agent — templates, a written description, or manual configuration — and when to use each." productArea: agents audience: ["business-user"] tags: ["agents", "getting-started"] lastReviewed: 2026-07-28 --- # Agent creation wizard (/agents/creation-wizard) **Agents → New Agent** offers three routes to the same result: a configured agent you can then edit like any other. ## Which route to use [#which-route-to-use] | Route | Best when | What you get | | --------------- | -------------------------------------------------- | -------------------------------------------------------------------------- | | **Template** | Your use case is a common one | A working agent with prompts, skills and often a data table already set up | | **Describe it** | You know what you want but not how to configure it | A drafted configuration generated from your description | | **Manual** | You know exactly what you want | An empty agent you fill in yourself | ## Templates [#templates] Pick a [template](/agents/templates) and it is copied into your workspace as a new agent. Everything is editable afterwards — the template is a starting point, not a constraint. This is the fastest route and the easiest to learn from, because you can open each tab and see how a working agent is put together. ## Describe it [#describe-it] Write what the agent should do in your own words, and KlicForge drafts the configuration from your description: identity, tone, capabilities, audience, and a suggested model. The more specific your description, the better the result. Say who the agent talks to, what it should refuse, and what a good answer looks like. If you already have prompt content written — an identity, a tone guide — include it in the description. Authored sections are used as written rather than being rewritten. Review everything before publishing. A drafted configuration is a first pass, not a finished agent. ## Manual [#manual] Set the name, description and model, then configure skills, knowledge, tools and guardrails from their tabs. Nothing is pre-filled. ## After the wizard [#after-the-wizard] Whichever route you took, the next steps are the same: 1. Attach a [knowledge source](/knowledge) so the agent has something to answer from. 2. Review [guardrails](/guardrails), especially the answer mode. 3. Test in the **Sandbox** tab. 4. Set status to `active` and connect a [channel](/channels). ## Related pages [#related-pages] * [Create your first agent](/getting-started/create-your-first-agent) * [Agent templates](/agents/templates) * [Core prompt files](/agents/core-prompt-files) --- title: "Domain packs" url: "/agents/domain-packs" description: "Tell KlicForge what kind of business an agent serves, so memory and business intelligence extract the right things." productArea: agents audience: ["business-user", "admin"] tags: ["domain-packs", "memory", "business-intelligence"] lastReviewed: 2026-08-25 --- # Domain packs (/agents/domain-packs) A domain pack is configuration that tells KlicForge what kind of business an agent serves, so the platform knows what to extract, remember, and track across conversations. Without one, KlicForge treats every conversation generically. With one, an agent's [memory](/memory) and business intelligence become domain-aware — they extract the right entity types, event types, and memory keys for that specific business context. ## Why configure a domain [#why-configure-a-domain] Before you can enable memory on an agent, you must select a business domain. This is a deliberate gate — the extraction pipeline needs to know what to look for (orders, appointments, student progress) to produce useful output instead of noise. [Business intelligence](/intelligence) does not share this gate — it discovers your business's vocabulary from your own conversations, so a domain pack is an optional head start rather than a precondition. Configuring a domain has no plan requirement of its own — every plan can select one. Memory requires a plan that includes it and stays locked until a domain is configured. Business intelligence has no plan requirement and no domain requirement — it is available on every plan with nothing to configure first. ## The intelligence layer [#the-intelligence-layer] On the agent's **Settings** tab, the **Intelligence Layer** section groups three settings: 1. **Business domain** — pick packs from the catalog. Configure this first if you plan to use memory. 2. **Memory** — persistent per-contact memory across conversations. 3. **Business intelligence** — event extraction and a self-building vocabulary of your business. See [Intelligence](/intelligence). ## Pack catalog [#pack-catalog] KlicForge ships 15 domain packs across three categories. ### Core packs [#core-packs] | Pack | Best for | | ------------------------- | -------------------------------------------------------------------- | | Generic business | Always included automatically — baseline extraction for any business | | Contact and CRM memory | Remembering contacts, their preferences, and relationship history | | Tasks and follow-ups | Action items, reminders, and follow-up tracking | | Documents and knowledge | Document requests, knowledge references, policy lookups | | Appointments and bookings | Scheduling, reservations, and booking management | ### Vertical packs [#vertical-packs] | Pack | Best for | | ---------------------- | ------------------------------------------------ | | Commerce and orders | Orders, products, payments, and delivery | | Delivery and logistics | Dispatch, tracking, and last-mile delivery | | Customer support | Support tickets, issue resolution, escalations | | Professional services | Client cases, engagements, and case management | | Education and tutoring | Lessons, progress, and learning goals | | Personal assistant | Daily tasks, personal preferences, and lifestyle | ### Sensitive packs [#sensitive-packs] These handle personally sensitive data and display an elevated or restricted badge in the dashboard. Select them only when the use case genuinely requires it. | Pack | Best for | | ----------------------- | ------------------------------------------------------------- | | Legal | Case facts, legal references, and regulatory matters | | Healthcare and wellness | Health data, symptoms, care instructions | | Children's education | Child learning data, with additional privacy controls applied | | Finance and advisory | Financial data, goals, portfolio references | ## Selecting packs [#selecting-packs] From the agent's **Settings** tab, under **Intelligence Layer → Business Domain**: 1. Choose a **primary pack** — the main domain this agent serves. This sets the primary extraction schema. 2. Optionally add **secondary packs** to extend coverage — for example, a catering agent might use Commerce and Orders as primary, with Appointments and Bookings and Delivery and Logistics as secondary. **Generic Business** is always active and never needs to be selected — it applies automatically as a baseline, so even an agent with no explicit pack configuration produces useful memory output. When you create an agent from a template, the wizard applies the template's recommended packs automatically. Change them afterward from the agent's Settings. ## How packs affect extraction [#how-packs-affect-extraction] When a conversation ends, extraction reads the applied packs and uses their entity types, event types, and memory key hints to guide what becomes a memory atom — a commerce pack extracts preferred items and delivery preferences, an education pack extracts lesson topics and learning gaps. The same pass produces the [business intelligence](/intelligence) events. A pack is a **head start, not a limit**. Its event types are offered as the preferred vocabulary, and anything your conversations turn out to be about that no pack anticipated is still recorded — a restaurant discussing halal certification, an agency discussing viewing times. Nothing is discarded for not appearing in a pack. What a pack adds beyond the names is the shape of each event: what the type means, which [labels](/intelligence#what-each-event-records) it should be countable by, and which details to capture. The Tasks and Follow-Ups pack is what tells extraction that a created task should record what it is about as a label while keeping the task's own wording in the encrypted detail — so attaching a pack that fits your business makes the resulting events far more useful to count, even though you would get events either way. ## Common configurations [#common-configurations] | Use case | Primary pack | Secondary packs | | --------------------------- | ---------------------- | ------------------------------------------------- | | Catering or food ordering | Commerce and Orders | Appointments and Bookings, Delivery and Logistics | | Home-based business | Commerce and Orders | Delivery and Logistics, Customer Support | | Personal assistant | Personal Assistant | Tasks and Follow-Ups, Appointments and Bookings | | Financial advisor assistant | Finance and Advisory | Contact and CRM Memory, Tasks and Follow-Ups | | Tutor or homework help | Education and Tutoring | Children's Education | | Customer support agent | Customer Support | Contact and CRM Memory | ## Related pages [#related-pages] * [Agents](/agents) * [Memory](/memory) --- title: "Agents" url: "/agents" description: "What an agent is, how it is configured, and what each tab in the agent editor controls." productArea: agents audience: ["business-user"] tags: ["agents"] lastReviewed: 2026-08-26 --- # Agents (/agents) An agent combines an identity, a model, skills, tools, knowledge sources and safety guardrails into one deployable unit. Agents are configured entirely in the dashboard — creating or changing one requires no code. ## Managing agents [#managing-agents] In the dashboard at [app.klicforge.ai](https://app.klicforge.ai): * **List agents** — open **My Agents** in the sidebar and select **Manage agents** to see every agent with its status, model and description. See [finding your way around](/getting-started/dashboard-navigation). * **Create an agent** — **Create new** opens [the creation wizard](/agents/creation-wizard). * **Edit an agent** — select any agent to open its detail view. * **Change status** — use the status control on the Overview tab. * **Test** — use the agent's **Sandbox** tab, or the preview on the agent's Widget tab. ## The agent editor [#the-agent-editor] | Tab | What it controls | | ------------------- | ------------------------------------------------------------------------- | | **Overview** | Metadata, current model, attached skills, tools and knowledge sources | | **Model** | The model this agent runs on, plus fallback models | | **Skills** | Which [skills](/skills-and-tools) are attached | | **Tools** | Which [tools](/skills-and-tools/tools) the agent may call | | **Guardrails** | Per-agent [safety controls](/guardrails) | | **System Prompt** | The four [core prompt files](/agents/core-prompt-files) | | **Channels** | Connect [Telegram, WhatsApp and other channels](/channels) | | **Conversations** | A read-only index of every [conversation](/conversations) with this agent | | **Scheduled Tasks** | [Proactive and recurring messages](/scheduled-tasks) | | **Evaluations** | [Test suites and runs](/evaluations) for this agent | | **Widget** | Widget appearance and the embed snippet | | **Settings** | Name, description, session behaviour, escalation, memory and versioning | [Knowledge sources](/knowledge) are chosen when you create the agent. To change them afterward, ask the [in-dashboard assistant](#editing-with-the-assistant) rather than looking for a Knowledge tab. ## Editing with the assistant [#editing-with-the-assistant] Instead of working through the editor tabs, you can describe the change to the [in-dashboard assistant](/troubleshooting/support#in-dashboard-assistant) — "make replies shorter", "add a starter question about refunds", "stop it offering follow-ups". The assistant proposes a **change set**: a card in the chat listing what would change, with a risk level (low for cosmetic or additive edits, medium for behavioural ones, high for destructive or breaking ones). Review it, then **approve** to apply or **discard**. Nothing is applied without approval, and the card keeps its status — approved, applied or discarded — when you come back to the conversation later. A change set can touch the [core prompt files](/agents/core-prompt-files), communication style, starter questions, name and description, model and fallbacks, skills, tools, [knowledge sources](/knowledge), guardrails and escalation — knowledge sources included, even though editing them isn't available from the editor tabs. For a [versioned agent](/agents/versioning), an applied change set edits the draft — production stays on the published version until you publish. The same approval flow covers edits to your [custom skills](/skills-and-tools#writing-one-with-the-assistant) — the card names the skill it changes rather than an agent. ## Status [#status] | Status | Behaviour | | ---------- | -------------------------------------------------------------------- | | `active` | Accepts messages and responds normally | | `inactive` | Rejects incoming messages with an unavailable notice | | `draft` | Visible in the dashboard, not reachable from the widget or a channel | ## Model and fallbacks [#model-and-fallbacks] Each agent runs on one model chosen from the catalog. You can add **fallback models** so the agent automatically retries with an alternative if the primary is unavailable. **Temperature** (0.0–1.0) controls consistency. Lower values produce more precise, repeatable answers; higher values are more conversational. Support and factual agents generally want 0.1–0.4. ## Sessions [#sessions] * **Session TTL** — how long a conversation stays active without activity. Once it expires, the next message starts a fresh conversation. Defaults differ per channel. * **Max messages** — how much conversation history is carried as context. ## Voice and point of view [#voice-and-point-of-view] The **Communication Style** card controls how an agent sounds, including its **point of view**: | Point of view | Effect | | -------------------------- | ----------------------------------------------------------------------- | | **Speaks as the business** | Answers use "we" and "our" — "our rates start at…" | | **Neutral assistant** | Answers as a helpful third party rather than a representative | | Unset | No instruction is added; the agent's wording is governed by its prompts | Content retrieved from your knowledge sources is always treated as your workspace's own material, so an agent does not describe your business from the outside regardless of this setting. ## Activity display [#activity-display] The **Settings** tab controls what a contact sees while the agent works: * **Activity display mode** — from nothing but a typing indicator through to a step-by-step timeline with timings. * **Collapse activity after response** — hide the activity block once the answer arrives. * **Send an interim reply** — the agent opens with one short line about what it is doing, written for that specific question in its own voice. Off by default, and unavailable when activity display is off. ## Memory and intelligence [#memory-and-intelligence] The **Settings** tab groups the intelligence features: 1. **Business domain** — tells the platform what kind of business this agent serves. Must be set before memory can be enabled, and gives [Business Intelligence](/intelligence) a head start, though it is optional there. See [domain packs](/agents/domain-packs). 2. **Memory** — persistent per-contact memory across conversations. Requires a business domain and a plan that includes it. See [memory](/memory). 3. **Business intelligence** — structured event extraction and a self-building vocabulary of your business, on every plan with nothing to configure first. See [Intelligence](/intelligence). ## Versioning [#versioning] By default every edit goes live immediately. Turning on **versioning** lets you edit a draft while production keeps serving the last published version, with history and rollback. See [agent versioning](/agents/versioning). ## Related pages [#related-pages] * [Creation wizard](/agents/creation-wizard) * [Templates](/agents/templates) * [Core prompt files](/agents/core-prompt-files) * [Agent versioning](/agents/versioning) * [Models](/agents/models) * [Domain packs](/agents/domain-packs) --- title: "Models" url: "/agents/models" description: "The model catalog, model tiers, and connecting your own provider account with bring-your-own-key." productArea: agents audience: ["business-user", "admin"] tags: ["models", "byok"] lastReviewed: 2026-08-21 --- # Models (/agents/models) Every agent runs on a model from the model catalog. Browse and assign models from the dashboard's **Models** page, or from the model drawer on an agent. ## Model catalog [#model-catalog] The catalog holds two kinds of entries: * **System defaults** — global models maintained by KlicForge, available to every workspace. * **Custom models (BYOK)** — models you add with your own API key, scoped to your workspace. ## Model tiers [#model-tiers] System models are grouped into tiers, and access is gated by your plan's capability tier. Higher tiers unlock more capable models. The dashboard shows a lock and an upgrade prompt on models above your current tier. ## Choosing a model [#choosing-a-model] | Use case | Look for | | ------------------------------------------------ | -------------------------------------------------------- | | Simple FAQ agents, lowest cost, fastest response | A fast, lower-tier model | | General-purpose agents | The balanced default tier — the best fit for most agents | | Complex decisions, multi-step reasoning | A higher-tier reasoning model | | Multi-language agents | A model with strong non-English support | | Document-heavy agents needing very large context | A model with an extended context window | Pair model choice with **temperature** (0.0–1.0): lower values produce more precise, repeatable answers; higher values are more conversational. Support and factual agents generally want 0.1–0.4. ## Reasoning effort [#reasoning-effort] Some models can work through a problem internally before they answer. On those models, the agent's model drawer shows a **Reasoning effort** setting with three levels: | Level | Use it for | | ------ | ----------------------------------------------------------------------------- | | Low | Straightforward questions where speed and cost matter more than depth | | Medium | A middle ground — more care than Low without Low's ceiling | | High | Multi-step decisions, ambiguous requests, anything the agent gets wrong today | More effort means a slower, more expensive answer, so raise it only where the extra care earns its keep. Leave it unset and the model reasons at its own default depth — a reasoning-capable model thinks through a request whether or not you pick a level, so the setting steers how much reasoning happens rather than whether it happens at all. The setting only appears on models that support it — pick a different model and it disappears, and the agent goes back to that model's default behaviour. The agent's internal reasoning is never shown to the person chatting, whichever level you choose — KlicForge actively watches for reasoning that leaks into a reply and rewrites the answer before it goes out, so an occasional slower or re-worded response from a reasoning-capable model is this working, not a fault. There is no separate switch to turn reasoning off; pick a model that does not reason if the extra latency is not worth it. ## Bring your own key (BYOK) [#bring-your-own-key-byok] Custom models route an agent to your own LLM provider account — useful for a specific model, your own rate limits, or your own billing relationship with a provider. ### Supported providers [#supported-providers] | Provider | API key required | Notes | | ---------- | ---------------- | --------------------------------------- | | OpenRouter | Yes | | | OpenAI | Yes | | | Ollama | No | Self-hosted; point at your own base URL | KlicForge's own platform-billed providers are not available for BYOK. ### Requirements [#requirements] Creating custom models requires the Pro capability tier (Business plan or higher), and is restricted to workspace owners and admins. ### Adding a custom model [#adding-a-custom-model] 1. Go to **Settings → Models**. 2. Select **Add custom model** and choose a provider. 3. Enter the model label, provider model ID, your API key (for OpenRouter or OpenAI), and an optional base URL. 4. Set capabilities — chat, image generation, video generation — plus input and output modalities and metadata such as context window and description. 5. Save. The model becomes available for assignment to any of your agents. ### How API keys are handled [#how-api-keys-are-handled] * Keys are write-only — the dashboard only ever shows whether credentials are set, never the key itself. * On edit, the key field is masked; select **Rotate key** to enter a new one. * Keys are encrypted at rest and used only transiently to authenticate outbound requests to the provider. They are never logged or stored in plaintext. ## Related pages [#related-pages] * [Agents](/agents) * [Plan limits](/reference/plan-limits) --- title: "Agent templates" url: "/agents/templates" description: "Pre-built agents for common jobs, copied into your workspace and fully editable." productArea: agents audience: ["business-user"] tags: ["agents"] lastReviewed: 2026-07-28 --- # Agent templates (/agents/templates) A template is a complete, working agent configuration for a common job. Choosing one copies it into your workspace as a new agent — prompts, skills, guardrails, and where relevant a [data table](/data-tables) already set up to capture what the agent collects. Everything is editable after creation. The template is a starting point. ## Using a template [#using-a-template] 1. Select **Agents → New Agent**. 2. Choose **Templates** and browse the gallery. 3. Select one to see what it includes before creating. 4. Create it, then adjust the name, prompts and knowledge for your business. You can also start from an agent template while browsing the [Marketplace](/marketplace) — selecting **Install Agent** on a listing opens the same wizard with that template already chosen. ## What a template brings [#what-a-template-brings] Depending on the template, some or all of: * The four [core prompt files](/agents/core-prompt-files), already written * A recommended model * Attached [skills](/skills-and-tools) * [Guardrail](/guardrails) settings suited to the job * A [data table](/data-tables) with fields and agent permissions configured Templates that capture personal information come with field permissions already set so the agent can write personal data but never read it back. If you add fields of your own, apply the same care — see [data table permissions](/data-tables#permissions). ## After creating from a template [#after-creating-from-a-template] A template does not know your business. Before publishing: 1. Rewrite the **IDENTITY** file so it describes your workspace, not a generic one. 2. Attach your own [knowledge sources](/knowledge). 3. Re-read the guardrails, particularly [answer mode](/guardrails/answer-modes). 4. Test in the agent's **Sandbox** tab. ## Related pages [#related-pages] * [Agent creation wizard](/agents/creation-wizard) * [Core prompt files](/agents/core-prompt-files) * [Data tables](/data-tables) --- title: "Agent versioning" url: "/agents/versioning" description: "Edit a draft while production keeps serving the last published version, with history and one-click rollback." productArea: agents audience: ["business-user", "admin"] plan: growth tags: ["agents", "versioning"] lastReviewed: 2026-07-28 --- # Agent versioning (/agents/versioning) By default every edit to an agent goes live the moment you save. Versioning separates the two: your agent becomes a **draft** you can edit freely, while production keeps serving the last **published version** until you publish again. Versioning is opt-in per agent. Until you publish a first version, edits go live instantly as before. ## Turning it on [#turning-it-on] Open the agent → **Settings** → **Versioning** → **Publish first version**. ## Publishing changes [#publishing-changes] When the draft differs from what is published, a banner appears on the agent page. | Action | What it does | | ----------- | ------------------------------------------------------------------------- | | **Publish** | Freezes the current draft as the new production version, live immediately | | **Discard** | Throws away draft changes and restores the published version | | **History** | Lists past versions and restores any of them | Publishing is idempotent — if nothing changed, KlicForge tells you it is already up to date rather than creating a duplicate. ### What Discard restores [#what-discard-restores] **Restored:** agent settings, model, skill/tool/knowledge selection, prompt files, widget configuration. **Not restored:** edits to shared skills, knowledge documents, connections, evaluation suites and scheduled tasks. These are shared resources that live outside the agent's own configuration. ## Rollback [#rollback] **Settings → Versioning → Version history** lists every published version, newest first. **Restore** points production back at that version. Your draft is untouched. Rollback is never blocked by an [evaluation publish gate](/evaluations) — it is the emergency path, and every target was live at some point already. ## What a version captures [#what-a-version-captures] A published version is a snapshot of the agent's full configuration: prompt files, model and fallbacks, temperature and session settings, attached skills and tools, the knowledge source list, guardrails and widget configuration. Two things are deliberately **not** frozen: * **Name, slug and status.** Renaming an agent or switching it to `inactive` still works while versioning is on, so the on/off switch never gets stuck behind a publish. * **Knowledge index content.** Only the *list* of attached knowledge sources is versioned, not the documents themselves. Re-uploading or re-embedding a source changes retrieval for every version, including old ones. That second point matters when comparing evaluation runs: a rerun of an old snapshot uses today's knowledge content, not the content as it was when the snapshot was taken. ## Testing before publishing [#testing-before-publishing] The agent's test chat has a **draft / published** toggle, so you can talk to your unpublished draft and the live version side by side before deciding. ## Plan limits [#plan-limits] | Plan | Versioning | Versions kept per agent | | ---------- | ---------- | ----------------------- | | Starter | — | — | | Startup | — | — | | Growth | ✓ | 5 | | Business | ✓ | 20 | | Enterprise | ✓ | Unlimited | "Versions kept" is a **rollback window** — how many recent versions stay restorable. Publishing a sixth version on Growth does not fail; the oldest simply drops out of the window. ## If you downgrade [#if-you-downgrade] Downgrading below Growth does not change what customers see — the agent keeps serving its published version. What stops is publishing. Edits still save to the draft but cannot be promoted. Two ways forward: 1. **Upgrade** back to Growth or above and carry on publishing. 2. **Turn versioning off** — production goes back to serving the live configuration and every edit takes effect immediately. Any unpublished draft changes go live at that moment. Version history is kept. Turning versioning off is available on every plan. ## Related pages [#related-pages] * [Agents overview](/agents) * [Evaluations](/evaluations) * [Plans and usage](/organization) --- title: "Developer overview" url: "/build" description: "What you can integrate with today — the widget SDK, custom webhook tools, and MCP servers — and what KlicForge does not yet offer." productArea: build audience: ["developer"] tags: ["developers"] lastReviewed: 2026-07-28 --- # Developer overview (/build) Most of KlicForge is configured in the dashboard rather than in code. This section covers the parts you integrate with programmatically. ## What you can build with [#what-you-can-build-with] | Surface | Use it to | | ----------------------------------------------- | ------------------------------------------------------------------------- | | [Widget SDK](/build/widget-sdk) | Embed the chat widget, control it from JavaScript, react to events | | [Custom webhook tools](/skills-and-tools/tools) | Let an agent call your own HTTP API | | MCP servers | Connect an agent to an external system through the Model Context Protocol | ## What KlicForge does not currently offer [#what-klicforge-does-not-currently-offer] **There is no public REST API with API keys.** KlicForge does not issue API keys or bearer tokens, and there is no general-purpose developer API for managing agents, contacts or data from your own backend. The dashboard is the management surface. Also not available today: * **Outbound webhooks.** KlicForge does not post events to your endpoints when something happens. To react to a conversation, have the agent call one of your [custom webhook tools](/skills-and-tools/tools) instead. * **Server-to-server chat.** The endpoints the widget uses are tied to an allowed-origin browser context and are not a substitute for a server API. If your integration depends on either, say so through support — knowing what people need shapes what gets built. ## Custom webhook tools [#custom-webhook-tools] The practical way to connect KlicForge to your own systems today. You define the endpoint, method, parameters and auth headers in the dashboard; the agent calls it during a conversation and uses the result in its answer. This inverts the usual integration direction: instead of KlicForge notifying you, your agent asks you at the moment it needs to know. For most workflows — look up an order, create a ticket, check availability — that is the more useful shape anyway. See [tools](/skills-and-tools/tools) for how to define one. ## MCP servers [#mcp-servers] An agent can connect to an external system through the Model Context Protocol, which exposes that system's tools to the agent. Connect providers under **Settings → MCP Providers**, then choose which of their tools each agent may use. ## Agent configuration as files [#agent-configuration-as-files] An agent's behaviour lives in four Markdown files — IDENTITY, SOUL, AGENTS and USER — which you can edit in the dashboard. They are worth understanding even if you never touch the platform programmatically, because they are where an agent's behaviour actually comes from. See [core prompt files](/agents/core-prompt-files). ## Related pages [#related-pages] * [Widget SDK](/build/widget-sdk) * [Tools](/skills-and-tools/tools) * [Web widget](/channels/web-widget) --- title: "Widget SDK" url: "/build/widget-sdk" description: "Embed and control the KlicForge chat widget from JavaScript — installation, configuration, methods and events." productArea: build audience: ["developer"] tags: ["widget", "sdk"] lastReviewed: 2026-08-25 --- # Widget SDK (/build/widget-sdk) The widget SDK embeds the KlicForge chat widget in a web page and gives you a JavaScript API to control it. The widget renders inside an isolated container, so its styles cannot leak into your page and your page's styles cannot break it. ## Installation [#installation] Add this before the closing `` tag: ```html ``` This registers `window.AgentKit` synchronously. ```bash npm install @bymos/agentkit-sdk ``` ```jsx import { useEffect } from 'react'; import { init } from '@bymos/agentkit-sdk'; export function ChatWidget() { useEffect(() => { const widget = init({ agentId: 'your-agent-id', tenantId: 'your-tenant-id', apiBaseUrl: 'https://api.klicforge.ai', }); return () => widget.destroy(); }, []); return null; } ``` Not using React? Call `init(config)` once, after your page has loaded, and keep the returned instance around to call `destroy()` yourself when you're done with it. Find your agent ID and workspace ID in the dashboard, and get a ready-made copy-paste snippet on the agent's **Sandbox** tab, or from an agent's **Channels → Widget** settings. The widget only loads on domains listed in the agent's allowed origins. If you see an access-restricted message, add the site's origin under the agent's **Channels → Widget** settings. ## Mounting [#mounting] `init()` creates a floating widget with a launcher button. To embed the chat inside an element of your own layout instead, use `mount()`: ```js window.AgentKit.mount(document.getElementById('support-chat'), { agentId: 'your-agent-id', tenantId: 'your-tenant-id', apiBaseUrl: 'https://api.klicforge.ai', }); ``` ## Configuration [#configuration] `init()` and `mount()` accept these fields: | Field | Type | Notes | | ----------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `agentId` | `string` | Required. | | `apiBaseUrl` | `string` | Required. | | `tenantId` | `string` | Tenant/organisation identifier. Required for conversation tracking and widget validation. | | `user` | `object` | Identity of the end-user — see [Identifying your users](#identifying-your-users). | | `sessionId` | `string` | Resume a specific session instead of the one persisted in `localStorage`. | | `mode` | `'floating' \| 'inline'` | Default `'floating'`. Use `'inline'` with `mount()` to embed in an element of your layout. | | `title` | `string` | Default `'AI Assistant'`. Overrides the agent's display name in the header. | | `subtitle` | `string` | Short text shown below the agent name in the widget header. | | `description` | `string` | Used in the widget empty state. Defaults from the server; can be overridden here. | | `avatarUrl` | `string` | URL of the avatar image shown in the header and launcher. | | `theme` | `object` | `mode` (`'light' \| 'dark' \| 'system'`), `accentColor`, `fontFamily`, `borderRadius`. | | `metadata` | `Record` | Arbitrary metadata attached to the session. | | `streaming` | `boolean` | Default `true`. Set `false` to receive whole replies instead of token streams. | | `preview` | `boolean` | Dashboard sandbox only. Sends the session cookie so a signed-in tenant member can chat with a draft/inactive agent. Leave `false` for third-party embeds. | | `skipServerConfigFetch` | `boolean` | Dashboard sandbox only. Skips the SDK's own config fetch when the host already supplies display fields inline. | | `configChannel` | `'draft' \| 'published'` | Dashboard sandbox only. `'draft'` requires a session cookie for the owning tenant and is inert for third-party embeds. | ## Controlling the widget [#controlling-the-widget] Both `init()` and `mount()` return an instance: ```js const widget = window.AgentKit.init({ ... }); widget.open(); widget.close(); widget.toggle(); widget.sendMessage('Hello'); widget.reset(); // start a fresh conversation widget.getState(); widget.destroy(); ``` `window.AgentKit.destroy(id)` removes a widget by ID, and calling it with no argument removes all of them. ## Events [#events] ```js widget.on('message:received', (event) => { console.log(event); }); widget.off('message:received', handler); ``` | Event | Fires when | | ---------------------------------------------- | -------------------------------- | | `ready` | The widget has initialised | | `open` / `close` | The widget is opened or closed | | `conversation:started` | A new conversation begins | | `message:sent` | The user sends a message | | `message:received` | The agent's reply arrives | | `message:error` | A message fails | | `stream:start` / `stream:delta` / `stream:end` | Streaming reply lifecycle | | `control_mode_changed` | A human takes over or hands back | | `reset` | The conversation is reset | | `destroy` | The widget is torn down | ## Identifying your users [#identifying-your-users] If you already know who the visitor is, pass an external identifier so their conversations link to the same [contact](/contacts) across sessions and devices. ```js window.AgentKit.init({ agentId: 'your-agent-id', tenantId: 'your-tenant-id', apiBaseUrl: 'https://api.klicforge.ai', user: { externalId: 'user_123', // your own DB user ID, UUID, etc. authId: 'auth0|abc123', // ID from your auth system — highest-priority lookup key name: 'Jane Doe', email: 'jane@example.com', }, }); ``` All `user` fields are optional — omit `user` entirely for anonymous sessions. Do not pass personal data you would not want in a browser. The identifier should be an opaque ID from your own system, not an email address. ## Appearance [#appearance] Greeting, branding, colours, whether file upload and voice notes are enabled, and links to your privacy policy and terms are configured on the agent's **Widget** tab, so non-developers can change them without a deployment. `title`, `avatarUrl`, and `theme` in the init config override those defaults for a specific embed when set — see [Configuration](#configuration). ## Sessions [#sessions] A conversation persists across page loads in the browser, so a visitor who navigates around your site keeps their conversation. `reset()` starts a fresh one. Sessions expire after a period of inactivity set on the agent. From 0.8 the SDK also establishes an abuse-protection session when the visitor opens the chat panel. It needs no configuration, adds nothing to a page whose chat is never opened, and a failure to establish one never blocks a message. ## Troubleshooting [#troubleshooting] | Symptom | Likely cause | | ------------------------------ | ----------------------------------------------------------------- | | `window.AgentKit is undefined` | The script tag runs after your init code, or failed to load | | Access-restricted message | The origin is not in the agent's allowed origins | | Widget opens but never replies | The agent's status is `draft` or `inactive` | | Widget is clipped or invisible | A parent element has `overflow: hidden` or a low stacking context | | Uploads rejected | The file type or size is not supported | ## Related pages [#related-pages] * [Web widget](/channels/web-widget) * [Developer overview](/build) * [Contacts](/contacts) --- title: "Public demo links" url: "/channels/demo-links" description: "Share a live preview of an agent floating over a prospect's own website, with an editable written summary of what it does — before embedding anything." productArea: channels audience: ["business-user"] tags: ["channels", "widget", "demo"] lastReviewed: 2026-08-25 --- # Public demo links (/channels/demo-links) A demo link is a public, unauthenticated page that shows your agent floating over a prospect's own website, next to a short written explanation of what it does. Send it before the prospect has agreed to embed anything on their site. ## Creating a demo link [#creating-a-demo-link] 1. Open the agent and select its **Sandbox** tab. 2. Select **Share demo**. 3. Enter the prospect's website address. It's shown as a backdrop behind the widget, so the demo looks like it's already running on their site. 4. Choose how long the link stays active — 7, 14, 30 or 90 days. 5. Turn the toggle on and copy the link. The agent must be **active** to turn a demo on — the same requirement as embedding it for real. ## What the prospect sees [#what-the-prospect-sees] The prospect's own site rendered behind a live, working copy of your widget, plus a panel explaining what the agent does, what it knows about, and questions they can try — written automatically from the agent's configuration, and editable before you send it. Some websites do not allow being shown inside another page. When that happens, KlicForge shows a neutral placeholder backdrop instead of the prospect's real site — the widget itself still works normally. ## How the demo looks [#how-the-demo-looks] The demo uses the appearance you set in the agent's **Sandbox** tab under **Theme** — **Mode**, **Accent Color**, **Font** and **Border Radius** — and the **Streaming responses** toggle under **Behaviour**. Select **Apply & Remount** to preview a change, then **Save** in the **Share demo** drawer to store it on the demo. The drawer lists the theme it will save, above the button. A demo you created earlier keeps the standard appearance until you save it again. **System** follows the prospect's own device setting, so the widget matches whatever they are already using. ## It's a real conversation [#its-a-real-conversation] Anyone holding the link can talk to the agent. A demo conversation is a real conversation — it creates a contact, is saved like any other, and counts against your [interaction allowance](/reference/interaction-counting) the same way a conversation on your real site would. Unlike [the web widget](/channels/web-widget), a demo link needs no allowed-origin configuration — it works immediately because it's served from KlicForge's own domain, not the prospect's. ## Editing the summary [#editing-the-summary] The written explanation is generated automatically and can be edited or regenerated at any time from the same drawer. Regenerating replaces anything you've edited — you'll be warned before it overwrites edited copy. ## Expiry and revoking access [#expiry-and-revoking-access] Demo links expire automatically. **Renew** extends an active link by another 30 days. **Rotate** immediately invalidates the current link and issues a new one — anyone holding the old link loses access right away. Rotate the moment a demo is no longer needed, rather than waiting for it to expire. Turning the toggle off has the same effect as expiry: the link stops working, indistinguishable from one that never existed. ## Troubleshooting [#troubleshooting] | Symptom | Likely cause | | --------------------------------------------------- | --------------------------------------------------------------------------------- | | Can't turn the demo on | The agent is not **active** yet | | The prospect's site does not appear as the backdrop | The site blocks being framed — a neutral placeholder is shown, widget still works | | Link says "not available" | The demo is off, or the link was rotated | | Link says the demo has expired | Renew it, or share the new link after rotating | ## Related pages [#related-pages] * [Web widget](/channels/web-widget) * [Widget SDK](/build/widget-sdk) * [Interaction counting](/reference/interaction-counting) --- title: "Escalate to human" url: "/channels/handoff" description: "Let an agent hand a conversation to a human operator when it cannot help, or the user insists on one." productArea: channels audience: ["business-user", "admin"] tags: ["escalation", "handoff"] lastReviewed: 2026-08-22 --- # Escalate to human (/channels/handoff) Escalation lets an agent hand a conversation to a human operator when it cannot help, the user insists on a human, or the issue is high-stakes. When an agent escalates, KlicForge notifies the configured operators and surfaces the conversation in the **Inbox**, under **Needs Attention** in the dashboard, where an operator can take over and reply directly. ## How it works [#how-it-works] Escalation combines three things that are kept in lockstep: a tool the agent calls to escalate, a skill that tells the agent when to escalate, and per-agent configuration. Enabling escalation on an agent attaches the tool and skill automatically — you never wire them up by hand. ## Enabling escalation [#enabling-escalation] On the agent's **Settings** tab, in the **Escalation** section: 1. Turn on **Enable escalation**. 2. Select which team members are notified when an escalation happens. Defaults to whoever enables it. 3. Optionally choose a custom detection skill to override when the agent decides to escalate. Creating an agent from a [template](/agents/templates) that includes the handoff tool turns escalation on for you automatically — if your workspace is on a paid plan and you have a verified Telegram account. Otherwise it stays off, exactly as above, ready to enable by hand. ## What happens at runtime [#what-happens-at-runtime] 1. The agent decides to escalate and calls the escalation tool with a reason and an optional summary. 2. KlicForge notifies each configured operator — see [notifications](/organization/notifications). 3. The conversation appears in the **Inbox**, where an operator can take over and reply to the user directly. 4. If nobody takes it over, the same operators get a follow-up reminder. Taking over, or a colleague doing so, clears it — you won't be reminded about a conversation someone already has. An agent also escalates automatically if it hits its tool-iteration limit while escalation is enabled. ## Requirements [#requirements] * **At least one notification channel** must be configured so operators can receive the alert — see [notifications](/organization/notifications). * **At least one operator** must be selected, or escalation cannot be dispatched. * Delivery to each operator is independent — if one operator's channel fails, the others still receive the alert. ## Related pages [#related-pages] * [KlicForge Inbox](/conversations/inbox) — where operators pick up an escalated conversation * [Channels](/channels) * [Notifications](/organization/notifications) --- title: "Channels" url: "/channels" description: "How people reach your agent — the web widget, Telegram, WhatsApp and the inbox." productArea: channels audience: ["business-user"] tags: ["channels"] lastReviewed: 2026-08-16 --- # Channels (/channels) A channel connects an agent to somewhere people can talk to it. Channels are configured per agent, on the agent's **Channels** tab. | Channel | What it is | | ---------------------------------- | --------------------------------------------------------------- | | [Web widget](/channels/web-widget) | A chat widget embedded in your website | | [Telegram](/channels/telegram) | A Telegram bot | | [WhatsApp](/channels/whatsapp) | WhatsApp Business messaging | | Inbox | An in-app channel for conversations without an external channel | Channels deliver to **your end users**. Alerting **your own team** — when a lead is captured or an agent asks for help — is a separate system configured under Notifications in the dashboard. ## The inbox [#the-inbox] The inbox is a built-in channel, one per workspace. It captures conversations that arrive without a dedicated external channel and shows them in the dashboard for your team. * Created automatically on first use — you never create it manually. * Cannot be deleted. Disable it in channel settings if you do not want it. * Shared across all agents in the workspace. ## Access control [#access-control] The web widget, Telegram and WhatsApp channels each decide who may reach the agent. Open the channel from the agent's **Channels** tab and use the **Allow List** and **Deny List** tabs. ### Access mode [#access-mode] Every channel is either **Open** or **Restricted**. The setting is at the top of the **Allow List** tab. | Mode | Who gets through | | -------------- | -------------------------------------------------------------- | | **Open** | Anyone, except contacts on the deny list. This is the default. | | **Restricted** | Only the allow list. The deny list still applies on top. | The deny list applies in both modes, and deny always wins over allow. Both lists stay editable whichever mode you are in, so you can prepare an allow list before switching to **Restricted**. Switching a channel to **Restricted** with an empty allow list blocks everyone. Add the entries first, then switch. ### Who you can add [#who-you-can-add] Search the box on either tab and pick from two kinds of entry. * **A contact** — someone who has messaged this agent before, so they already have a contact record. See [contacts](/contacts). * **A data table row, or a whole data table** — pick one row, or **Everyone in this table** to cover every row in it. A whole-table entry is resolved each time someone messages, so adding a row to the table grants access without touching the channel. See [data tables](/data-tables). Data table entries let you authorise someone **before they ever message**, which a contact entry cannot do. Only tables with at least one identity column can be picked — a column typed `whatsapp_id`, `telegram_id`, `telegram_handle`, `phone` or `email`. That column is what an incoming sender is matched against, and an entry names which of its columns it matches on. The search box lists what you can add as soon as you open it, so you can browse rather than guess at a search term. It offers only data tables this agent has read permission on — if one is missing, grant it from the table's **Permissions** tab, see [permissions](/data-tables#permissions). Data table entries authorise Telegram and WhatsApp senders, whose identity the messaging platform confirms. They do not authorise web widget visitors — see [restricting the widget](/channels/web-widget#restricting-who-can-chat). ### Example [#example] To let only your customers use a WhatsApp agent: keep a data table with a `whatsapp_id` column, add **Everyone in this table** to the channel's allow list, then set the channel to **Restricted**. To bar one number afterwards, add that row to the deny list — you do not have to remove it from the table. ## Handing over to a human [#handing-over-to-a-human] An agent can escalate a conversation to a person. When it does, your team is notified and can take over the conversation from the dashboard, reply directly, and hand control back to the agent afterwards. See [escalate to human](/channels/handoff) for how to configure it. ## Security [#security] * Channel credentials — bot tokens, access tokens — are **write-only**. They are stored encrypted and never appear in the dashboard or in any API response after you save them. * If your API URL changes, reconnect the channel so the webhook is re-registered. ## Troubleshooting [#troubleshooting] | Symptom | Likely cause | | ------------------------------------ | --------------------------------------------------------------- | | Messages are not reaching the agent | Agent status is `draft` or `inactive` | | The channel worked, then went silent | An expired credential — see [WhatsApp](/channels/whatsapp) | | Some people get no response | A deny list entry is filtering them | | Nobody gets a response | The channel is **Restricted** and the allow list matches nobody | | A widget visitor is refused | Data table entries do not authorise widget visitors | | Widget does not load | The site's domain is not in the agent's allowed origins | ## Related pages [#related-pages] * [Web widget](/channels/web-widget) * [Telegram setup](/channels/telegram) * [WhatsApp setup](/channels/whatsapp) * [Escalate to human](/channels/handoff) * [Contacts](/contacts) --- title: "Telegram setup" url: "/channels/telegram" description: "Connect a Telegram bot to your agent, including the slash commands users get automatically." productArea: channels audience: ["business-user"] plan: startup tags: ["channels", "telegram"] lastReviewed: 2026-08-14 --- # Telegram setup (/channels/telegram) Connecting a Telegram bot routes messages from Telegram to your agent and sends its replies back. It uses webhooks — Telegram pushes messages to KlicForge, so there is nothing to poll and nothing to host. ## Prerequisites [#prerequisites] * A Telegram account. * An agent with status `active`. * A plan that includes the Telegram channel. ## Connecting [#connecting] ### Create a bot [#create-a-bot] Message [@BotFather](https://t.me/BotFather) on Telegram, create a bot, and copy the token it gives you. ### Connect it [#connect-it] In the dashboard, open your agent's **Channels** tab and select **Connect Channel → Telegram**. Paste the bot token and save. ### Confirm [#confirm] KlicForge encrypts the token and registers the webhook with Telegram automatically. Message your bot to check it replies. ## Expected result [#expected-result] Messages sent to your bot are answered by the agent, and the conversations appear in the dashboard. ## Slash commands [#slash-commands] `/start` and `/reset` are registered with Telegram automatically when the channel connects, so they appear in the bot's command menu. `/help` is recognised in the message text like any other command, without appearing in that menu. | Command | What it does | | -------- | ----------------------------------------------------------------------------- | | `/start` | Starts a new conversation, keeping what the agent remembers about the contact | | `/reset` | Starts a new conversation and excludes the session from [memory](/memory) | | `/help` | Lists the commands available on this channel | `/start` and `/reset` answer immediately with a short greeting from the agent. The greeting is fixed text, so an agent cannot be prompted to look anything up before replying to a command. ## Group chats [#group-chats] A Telegram bot can be added to a group. Group behaviour is configurable so the agent responds only when it should — for example when mentioned — rather than to every message. ## Restricting who can chat [#restricting-who-can-chat] A Telegram bot is reachable by anyone who finds it, so a bot meant for staff or paying customers needs an allow list. Set the channel to **Restricted** on its **Allow List** tab and add the people who may use it. Entries can be contacts who have messaged before, or rows from a data table with a `telegram_id` or `telegram_handle` column — which is how you authorise someone who has not messaged yet. Telegram confirms the sender's identity, so these entries hold. See [access control](/channels#access-control). ## Disconnecting [#disconnecting] From the agent's **Channels** tab, select **Disconnect**. KlicForge deregisters the webhook with Telegram for you. ## Troubleshooting [#troubleshooting] | Symptom | Likely cause | | -------------------------------------------------- | ----------------------------------------------------------------------------------- | | Bot does not reply at all | Agent status is not `active`, or the token was mistyped | | Bot replies in direct messages but not groups | Group settings, or Telegram's own bot privacy mode | | Bot stopped working after an infrastructure change | The webhook URL changed — reconnect the channel | | Specific people get no reply | A deny list entry is filtering them | | Nobody gets a reply | The channel is **Restricted** and the allow list matches nobody | | Someone on the allow list is refused | Their handle is stored differently in the data table than the one they message from | ## Related pages [#related-pages] * [Channels overview](/channels) * [WhatsApp setup](/channels/whatsapp) * [Memory](/memory) --- title: "Web widget" url: "/channels/web-widget" description: "Embed the chat widget on your website, control how it looks, and restrict which domains may load it and who may chat." productArea: channels audience: ["business-user", "developer"] tags: ["channels", "widget"] lastReviewed: 2026-08-25 --- # Web widget (/channels/web-widget) The web widget is a chat window you embed in your website. It is the default way to put an agent in front of customers and the only channel available on every plan. ## Adding it to your site [#adding-it-to-your-site] 1. Open the agent's **Widget** tab. 2. Configure the appearance and greeting. 3. Copy the embed snippet. 4. Paste it into your site's HTML, before the closing `` tag. The widget loads in an isolated container, so it will not inherit or interfere with your site's styles. ## Configuration [#configuration] From the **Widget** tab you can set the greeting message, branding and colours, whether file upload is enabled, whether voice notes are enabled, and links to your privacy policy and terms. Attachments count towards usage — see [interaction counting](/reference/interaction-counting) before enabling uploads on a high-traffic site. ## Allowed origins [#allowed-origins] The widget only works on domains listed in the agent's **allowed origins**. This is what stops someone embedding your agent on their own site and spending your allowance. If the widget does not appear on your site, this is the first thing to check. Add every domain that should be able to load the widget, including staging domains. Requests from anywhere else are rejected. ## Restricting who can chat [#restricting-who-can-chat] Allowed origins control which **sites** may load the widget. To control which **people** may talk to the agent once it has loaded, use the **Allow List** and **Deny List** tabs on the widget channel. See [access control](/channels#access-control) for how the two modes work. On the widget, only contact entries take effect. A data table row or whole-table entry does not authorise a widget visitor, so a widget channel set to **Restricted** with only data table entries turns everyone away. Separately from any list you configure, KlicForge checks public widget traffic for automated abuse before a visitor's first message. There is nothing to set up and nothing for a genuine visitor to solve. A visitor arrives with whatever identity your page supplies through the SDK, and a browser can send anything. So a widget allow list is a convenience for a small, known audience, not a security boundary. When only certain people should reach an agent, put it on Telegram or WhatsApp — the messaging platform confirms who the sender is — or gate the page the widget sits on with your own login. ## Testing [#testing] Use the agent's **Sandbox** tab to talk to the agent exactly as a visitor would, without embedding anything. From the same screen, **Share demo** creates a public link a prospect can open before you embed anything on their site. See [public demo links](/channels/demo-links). ## For developers [#for-developers] The widget is also available as an npm package and a CDN bundle, with a JavaScript API for opening, closing, sending messages and listening to events. See [the widget SDK](/build/widget-sdk). ## Troubleshooting [#troubleshooting] | Symptom | Likely cause | | -------------------------------- | ------------------------------------------------------------------------------ | | Widget does not appear | The site's domain is missing from allowed origins | | Widget appears but never replies | Agent status is `draft` or `inactive` | | Widget looks wrong on your site | Check the container is not inside an element with `overflow: hidden` | | Every visitor is turned away | The channel is **Restricted** and the allow list holds only data table entries | | Uploads rejected | File type or size limit — see [knowledge](/knowledge) for supported types | ## Related pages [#related-pages] * [Channels overview](/channels) * [Widget SDK](/build/widget-sdk) * [Interaction counting](/reference/interaction-counting) --- title: "WhatsApp setup" url: "/channels/whatsapp" description: "Connect WhatsApp Business messaging, including the two Meta requirements that most often break the integration." productArea: channels audience: ["business-user", "admin"] plan: business tags: ["channels", "whatsapp"] lastReviewed: 2026-08-16 --- # WhatsApp setup (/channels/whatsapp) WhatsApp routes messages from the WhatsApp Business Cloud API to your agent and sends replies back. WhatsApp has more setup than other channels, and most of it happens on Meta's side rather than in KlicForge. Read the two critical requirements below before you start — they are the reason most WhatsApp integrations silently stop working. ## Prerequisites [#prerequisites] * A Meta Business account with a WhatsApp Business app. * A phone number registered to that app, not in use by the WhatsApp consumer app. * A plan that includes the WhatsApp channel. ## The two things that break WhatsApp [#the-two-things-that-break-whatsapp] **Use a permanent System User token, not a temporary one.** Tokens generated in the Meta Graph API Explorer expire after 24 hours. When one expires the channel goes dark with no warning in KlicForge — messages simply stop arriving. Generate the token from a **System User** under Meta Business Settings → Users → System Users. **Your agent cannot start a conversation.** Meta blocks any business-initiated message outside the 24-hour customer service window unless it uses a pre-approved message template. Send the first template message from WhatsApp Manager to open the window; the agent can then reply freely until it closes. ## Connecting [#connecting] ### Gather your Meta credentials [#gather-your-meta-credentials] From your Meta Developer app you need the **phone number ID**, a permanent **access token** from a System User, and a **verify token** of your choosing. ### Connect in KlicForge [#connect-in-klicforge] Open the agent's **Channels** tab, select **Connect Channel → WhatsApp**, enter the three values and save. Credentials are encrypted and never shown again. ### Register the webhook with Meta [#register-the-webhook-with-meta] Copy the webhook URL shown on the confirmation screen and register it in your Meta Developer console, using the same verify token. ### Test [#test] Message your WhatsApp business number and confirm the agent replies. ## Expected result [#expected-result] Messages to your business number are answered by the agent, and conversations appear in the dashboard. ## Slash commands [#slash-commands] WhatsApp has no command menu, so these are recognised in the message text — a contact types them like any other message. | Command | What it does | | -------- | ----------------------------------------------------------------------------- | | `/start` | Starts a new conversation, keeping what the agent remembers about the contact | | `/reset` | Starts a new conversation and excludes the session from [memory](/memory) | | `/help` | Lists the commands available on this channel | Commands are always answered directly, even when the connection is set to draft replies for human review — the reply is a fixed acknowledgement, not something an agent wrote. ## The 24-hour window [#the-24-hour-window] Meta allows free-form business replies only within 24 hours of the customer's last message. Outside that window you must use an approved template. This affects [scheduled tasks](/scheduled-tasks): a task delivering to WhatsApp requires an approved template, because there is no guarantee the window is open when it runs. ## Templates and quality [#templates-and-quality] Message templates are created and approved in WhatsApp Manager, not in KlicForge. Meta also applies quality ratings and messaging limits to your number, which can restrict how many conversations you can start. Those rules change regularly — check [Meta's own documentation](https://developers.facebook.com/docs/whatsapp) for current limits rather than relying on any figure reproduced here. ## Opting out of marketing messages [#opting-out-of-marketing-messages] A customer can reply **STOP** to any of your WhatsApp numbers and will stop receiving marketing templates from that workspace. `unsubscribe`, `optout`, `opt out` and `berhenti` do the same. They can reply **START** — or `unstop`, `subscribe`, `resume` — to start receiving them again. Either way KlicForge sends a short confirmation, and the agent does not see the message. **Only marketing templates are suppressed.** Utility and authentication templates — payment reminders, appointment notices, verification codes — keep going out to someone who has opted out, because they are transactional rather than promotional. Which of those a template is, is Meta's decision, not yours: the category is assigned when the template is approved and Meta can change it afterwards. Check a template's category in WhatsApp Manager if you are unsure whether an opt-out will suppress it. The keyword has to be the whole message. "Stop by the shop tomorrow" is an ordinary message and reaches the agent normally. `cancel`, `quit` and `end` are deliberately not opt-out words — they are ordinary things to say to an agent, and a booking agent that offers "reply CANCEL to cancel your appointment" would otherwise unsubscribe the customer instead. Opt-outs apply across every WhatsApp connection in the workspace, however it was set up, and they apply to [audience messages](/scheduled-tasks/audience-messages) as well as to anything an agent sends. ## Restricting who can chat [#restricting-who-can-chat] Anyone who has your WhatsApp number can message the agent. To limit it to a known audience, set the channel to **Restricted** on its **Allow List** tab and add the people who may use it. Entries can be contacts who have messaged before, or rows from a data table with a `whatsapp_id` or `phone` column — which is how you authorise a customer who has not messaged yet. Pick **Everyone in this table** and the list follows the table: add a customer row and they can message, without anyone touching the channel. See [access control](/channels#access-control). The picker offers only data tables this agent has read permission on. If a table you expect is missing, grant it from the table's **Permissions** tab — see [permissions](/data-tables#permissions). Store the number in the column the way the field type expects — a `whatsapp_id` column holds digits only, a `phone` column holds the international form beginning `+`. Either matches an incoming sender. ## Disconnecting [#disconnecting] From the agent's **Channels** tab, select **Disconnect**. ## Troubleshooting [#troubleshooting] | Symptom | Likely cause | | ---------------------------------------- | --------------------------------------------------------------- | | Worked for a day, then stopped | A temporary access token expired — reissue from a System User | | Meta rejects the webhook | Verify token does not match the one saved in KlicForge | | Agent cannot message a customer first | Expected — this needs an approved template and an open window | | Scheduled task to WhatsApp does not send | The task has no approved template selected | | Replies stop after a day of silence | The 24-hour window closed | | Nobody gets a reply | The channel is **Restricted** and the allow list matches nobody | | A customer on the allow list is refused | Their number is stored in a format the column does not expect | | A customer stopped getting marketing | They replied STOP — utility templates still reach them | | A data table is missing from the picker | The agent has no read permission on it | ## Related pages [#related-pages] * [Channels overview](/channels) * [Scheduled tasks](/scheduled-tasks) * [Audience messages](/scheduled-tasks/audience-messages) * [Contacts](/contacts) --- title: "Contacts" url: "/contacts" description: "The people your agents talk to — how they are identified, how their personal data is protected, and what you can do with their records." productArea: contacts audience: ["business-user", "admin"] tags: ["contacts", "privacy"] lastReviewed: 2026-08-25 --- # Contacts (/contacts) A contact is a person who talks to one of your agents. KlicForge creates a contact record the first time someone starts a conversation, and links their later conversations to it. Sending an [audience message](/scheduled-tasks/audience-messages) can also create the record — a recipient gets a contact the moment you message them, before they've said anything back. Find them under **Developer → Contacts** in the dashboard. ## How a contact is identified [#how-a-contact-is-identified] Identity depends on the channel: | Channel | Identified by | | ---------------------------------- | ------------------------------------------------------ | | [Web widget](/channels/web-widget) | An anonymous identifier, or an `externalId` you supply | | [Telegram](/channels/telegram) | Their Telegram user ID | | [WhatsApp](/channels/whatsapp) | Their WhatsApp number | A contact starts anonymous and becomes identified when it learns something identifying — a name or email the person gives during conversation, or an `externalId` you pass in from your own system when you already know who they are. ## Personal data [#personal-data] Contact names, email addresses, phone numbers and messaging identifiers are encrypted at rest. They are masked in the dashboard and revealed only through an explicit, audited action. Personal fields are also redacted automatically from audit logs. ## What is on a contact record [#what-is-on-a-contact-record] * Identity and contact details, as far as they are known * Conversation history across every channel * [Memory](/memory), if enabled — what the agent remembers about them * Category and tags you assign * Any [data table](/data-tables) records linked to them ## Controlling what an agent can see [#controlling-what-an-agent-can-see] An agent's access to contact information is governed by the tools and [data table permissions](/data-tables#permissions) you grant it. For public-facing agents, the safe pattern is to let the agent **write** personal data — so it can capture a name or email during conversation — while blocking it from **reading** those fields back. That way a stranger cannot ask your agent to recite someone else's details. ## Data requests [#data-requests] You can export everything held about a contact, which is what you need when someone exercises a right of access. Deletion requests are handled the same way. A contact's exported data includes their conversation history and their memory. Review what an export contains before sending it. ## Related pages [#related-pages] * [Memory](/memory) * [Data tables](/data-tables) * [Channels](/channels) * [Security and privacy](/organization/security-and-privacy) --- title: "KlicForge Inbox" url: "/conversations/inbox" description: "Handle live conversations from your phone — see which ones need a person, take over, reply, and get alerted the moment an agent asks for help." productArea: conversations audience: ["business-user", "admin"] tags: ["conversations", "handoff", "notifications"] lastReviewed: 2026-08-22 --- # KlicForge Inbox (/conversations/inbox) The **KlicForge Inbox** is a small app for the one job the dashboard is awkward at: being on call. It shows the conversations that need a person, lets you take one over and reply, and tells you the moment an agent asks for help — from your phone, without opening the dashboard. Open it at [inbox.klicforge.ai](https://inbox.klicforge.ai) and sign in with the same account you use for the dashboard. Everything you can do there, you can still do in the dashboard **Inbox**; the KlicForge Inbox app is a faster way to reach the same conversations, not a separate set of them. ## Install it on your phone [#install-it-on-your-phone] The Inbox is a web app, but it is meant to live on your home screen — and it offers to install itself on the sign-in screen, before you sign in. Do that first and there is nothing to repeat afterwards. * **Android** — tap **Install**. That is the whole thing; the app opens already signed in once you sign in. * **iPhone and iPad** — tap **Show me how**, then follow the three steps: Share button, **Add to Home Screen**, then open the Inbox from the new icon and sign in there. On iPhone and iPad, an app on the Home Screen keeps its **own** sign-in, separate from Safari. So if you sign in in Safari and install afterwards, the app opens asking you to sign in again — that is Apple's behaviour, not a fault. Installing first means signing in once. You can skip the prompt and sign in as normal. **Not now** only clears it for that visit — the offer waits for you again above the queue list once you are in, and closing it there with the **×** is what puts it away for good. Either way you can install at any time from **Settings → Tip: install the Inbox**, or your browser's own **Add to Home screen** menu item. On iPhone and iPad you must add the Inbox to your home screen **before** notifications can be turned on — Apple only allows web apps to send notifications once they are installed. The Inbox tells you this instead of offering a button that cannot work. ## The three queues [#the-three-queues] The Inbox opens on a queue list. Each queue counts only conversations that are still running. | Queue | What is in it | | ------------------- | -------------------------------------------------------------------------- | | **Needs Attention** | An agent has asked for a human and nobody has stepped in yet | | **Live** | Everything currently running, whether the agent or a person is handling it | | **Mine** | Conversations you have taken over and not yet released | **Needs Attention** is the one to watch. A conversation lands there when an agent [escalates](/channels/handoff) — because it could not help, or because the customer asked for a person — and it leaves as soon as somebody takes it over. ## Taking over a conversation [#taking-over-a-conversation] Open a conversation and select **Take over**. The agent stops replying and anything you send goes to the customer as you. When you are done, **Release** it: hand it back to the agent, or close the conversation if it is finished. This is the same handover described in [Conversations](/conversations) — releasing lets the agent pick up from the last unanswered message, and it can see what you said while you were in control, so it will not repeat itself. If a colleague has already taken a conversation over, you can see who has it. Owners and admins can take it from them; members cannot, so a conversation someone is actively handling is not pulled away underneath them. ## Chatting with your own agents [#chatting-with-your-own-agents] The bottom tab bar also has a **Chats** tab — the same conversations you have with your own agents from the dashboard's **Chats**, now on your phone. Pick an agent to start a session or continue one you left off, with attachments, slash commands and voice notes all working the same as the dashboard. See [Finding your way around](/getting-started/dashboard-navigation) for what Chats is for and how it differs from the Inbox queues above — Chats is you talking to your own agents, Inbox is everyone else's conversations with them. ## Getting alerted [#getting-alerted] The Inbox asks to turn alerts on the first time you reach your queues — tap **Turn on alerts** and your browser's own permission prompt appears. **Not now** puts it away for a week. You can also turn them on at any time under **Settings → Notifications**, which is always available whatever you chose in the prompt. After that, when an agent asks for a human, your phone gets an alert naming the agent that asked. Tapping it opens that exact conversation, ready to take over. If you accidentally block notifications, no prompt can bring them back — browsers only let a site ask once. The Inbox will tell you they are blocked and point you at your browser settings; re-allow them there, then turn them on from **Settings → Notifications**. Two deliberate details: * **The alert never contains customer content** — no name, no message text. It arrives on a lock screen, often in public, so it says only which agent needs help. * **One alert per conversation, not per colleague.** If several people are on call for the same agent, everyone is alerted, but nobody gets a stack of alerts for one conversation. Turning notifications on registers the device for **every workspace you belong to**, so you do not have to repeat it after switching. You can see and remove the devices you have registered from the same screen — removing one stops alerts to that device everywhere. The bell icon in the header holds the same feed a push alert draws from, so a notification you missed — or read before you had a device registered — is still there to catch up on. Beyond the initial escalation, you're also alerted if a conversation you're handling is reassigned, or if the customer replies while you have it — see [notification events](/organization/notifications#notification-events). If you turned notifications on and nothing arrives, check that your browser has not blocked them for the site. The Inbox says so on the Settings screen when that is the cause, because a blocked permission cannot be re-requested from inside the app. ## Working across workspaces and accounts [#working-across-workspaces-and-accounts] Tap the workspace name at the top of the queue to move between the workspaces you belong to. The queues, the conversations and your permissions all follow. If you belong to only one workspace, this stays out of your way. You can also sign in with a second account on the same phone and swap between them from the same panel — useful if you have a personal account and one from a client's workspace. Tapping a notification switches to the right account and workspace before opening the conversation, so an alert from one workspace never drops you into another. Signing out signs out **every** account on that device, and the Inbox says so when you have more than one. To move between workspaces or accounts, switch rather than sign out. ## Who can do what [#who-can-do-what] | Action | Members | Admins and owners | | --------------------------------------------- | ------- | ----------------- | | See the queues and read conversations | Yes | Yes | | Take over a conversation nobody is handling | Yes | Yes | | Reply and release | Yes | Yes | | Take over from a colleague who already has it | No | Yes | ## Related pages [#related-pages] * [Conversations](/conversations) — the full history, summaries and traces * [Escalate to human](/channels/handoff) — how an agent decides to ask for a person * [Notifications](/organization/notifications) — every channel alerts can arrive on --- title: "Conversations" url: "/conversations" description: "Read what your agents and customers said, take over a live chat, and diagnose why an agent answered the way it did." productArea: conversations audience: ["business-user", "admin"] tags: ["conversations"] lastReviewed: 2026-08-26 --- # Conversations (/conversations) Every exchange between an agent and a [contact](/contacts) is recorded as a conversation. Find them in the **Inbox** in the dashboard, on a contact's record, or on an agent's read-only **Conversations** tab. The Inbox groups them into queues — Needs Attention, Live, Mine, All and Resolved — which are filters over the same list rather than separate pages. The list carries a **Summary** column: a short recap written once the conversation has ended, so several sessions from the same contact can be told apart without opening each one. It stays blank while a conversation is still running, and — like the trace below — it is shown to workspace owners and admins only, since a recap says what was asked and what was answered. Members see the rest of the row. ## What a conversation shows [#what-a-conversation-shows] * Every message, in order, with timestamps * Which agent answered, and on which [channel](/channels) * Any [tools](/skills-and-tools/tools) the agent called, with their arguments and results * Attachments the contact sent, and files the agent sent back * Whether a human took over ## Taking over a live conversation [#taking-over-a-live-conversation] When an agent cannot help — or a customer asks for a person — your team can step in. 1. Open the conversation. 2. Select **Take over**. The agent stops responding. 3. Reply directly as yourself. 4. Select **Release** to hand control back. An agent can also request this itself. When it escalates, your team is notified and the conversation is flagged for attention. After you release a conversation, the agent picks up from the last unanswered message. It can see what you said while you were in control, so it will not repeat information you already gave. ## Diagnosing an answer [#diagnosing-an-answer] When an agent answers wrongly, the conversation view is where you find out why. For a given turn you can see: * **Which knowledge was retrieved** — if the right passage was not retrieved, the problem is your [knowledge source](/knowledge), not the model * **Which tools ran** — and what they returned * **Whether a guardrail intervened** — an off-topic refusal or a failed response validation looks like a bad answer but is the agent working as configured That distinction matters: retrieval problems are fixed by editing content, guardrail refusals by changing [guardrail settings](/guardrails), and genuinely wrong reasoning by changing the [prompt files](/agents/core-prompt-files) or the model. ### Where the time went [#where-the-time-went] The activity timeline names each step by what the agent did — "Searching knowledge base", "Gathering background information", "Checking the weather" — and shows the gap to the next step, so a slow answer can be traced to the step responsible rather than guessed at. Steps are ordered by when they happened, and gaps are not shown across a run boundary. What a contact sees of this is controlled by the agent's activity display mode, which is separate from what you see here. ### Trace view [#trace-view] When the timeline is not enough, open the **Trace** tab. It shows the same conversation without anything hidden — including the turns where the agent only called tools and said nothing, which the message view leaves out. Dashboard chat has its own **View trace** action in the chat menu, so you can check what an agent did without leaving the conversation you are having with it. For each turn you get: * **Every tool call**, with the exact arguments the agent sent and the result it received back — the same text the model saw, not a summary of it * **Whether each call succeeded**, so a wrong answer caused by a failed lookup is distinguishable from one caused by bad reasoning * **Which model answered** and how many tokens the turn used * A summary of the conversation's **interactions** and total tokens — interactions are the unit you are billed in, see [interaction counting](/reference/interaction-counting) Model and token figures are only recorded on some channels. Turns that came through Telegram, WhatsApp or a [scheduled task](/scheduled-tasks) show a dash instead — the answer itself is complete, only the per-turn measurements are missing. Where an agent revealed an encrypted field, the trace shows a placeholder in place of the value. That is what the agent itself received — the real value is put into its reply afterwards, and only there. See [revealing an encrypted value](/data-tables#revealing-an-encrypted-value). **Export** saves the whole trace as **Markdown**, for reading or attaching to a bug report, or as **JSON** for feeding into your own tooling. Both include the tool calls and annotations. The trace is limited to workspace owners and admins, because it exposes raw tool arguments and message content. Every time it is opened, that is recorded in the security audit log along with who opened it. See [security and privacy](/organization/security-and-privacy). ### Ask the assistant to diagnose it [#ask-the-assistant-to-diagnose-it] Instead of reading the trace yourself, you can ask the [in-dashboard assistant](/troubleshooting/support#in-dashboard-assistant) — "why did the agent get this wrong?", or hand it a conversation and ask what happened. It reads the trace and tells you which of the usual causes it was: unclear instructions, a knowledge gap, the wrong tool arguments, a missing tool grant, or genuinely wrong reasoning. From there it proposes a [change set](/agents#editing-with-the-assistant) to fix the agent, and can save the conversation as a regression case so the same failure is caught next time — see [reviewing a run with the assistant](/evaluations#reviewing-a-run-with-the-assistant). This is owner/admin only, like the trace itself, and every read is recorded the same way. ## When conversations end [#when-conversations-end] A conversation ends when it is explicitly closed, or after a period of inactivity set per channel and per agent. Once it ends: * It stops accepting new messages — the contact's next message starts a fresh conversation * It becomes eligible for [memory](/memory) extraction, if memory is enabled * A summary is generated ## Attachments [#attachments] Files and images a contact sends are stored and linked to the conversation. Each attachment counts towards your usage — see [interaction counting](/reference/interaction-counting). ## Related pages [#related-pages] * [KlicForge Inbox](/conversations/inbox) — handle live conversations from your phone * [Contacts](/contacts) * [Channels](/channels) * [Memory](/memory) * [Troubleshooting](/troubleshooting) --- title: "Data tables" url: "/data-tables" description: "Structured storage your agents can read from and write to — fields, personal data handling, and per-agent permissions." productArea: data-tables audience: ["business-user", "admin"] tags: ["data-tables"] lastReviewed: 2026-08-25 --- # Data tables (/data-tables) A data table is structured storage your agent can read from and write to during a conversation — like a spreadsheet the agent can use. Each table has a name, a permanent slug, typed fields (columns) and records (rows). Common uses: leads, support tickets, orders, bookings, and anything else an agent needs to capture or look up. ## Creating a table [#creating-a-table] Select **Data Tables** in the sidebar, then create a table and add fields. Then open the table's **Permissions** tab and grant your agent access — an agent cannot see a table until you do. ## Field types [#field-types] | Group | Types | | ------------------------ | -------------------------------------------------------------------------------------------- | | Basic | `text`, `long_text`, `number`, `currency`, `date`, `datetime`, `boolean`, `json`, `url` | | Selection | `single_select`, `multi_select`, `status` | | Identity / personal data | `email`, `phone`, `name`, `nric`, `address`, `whatsapp_id`, `telegram_id`, `telegram_handle` | | System | `auto_increment`, `uuid`, `contact_id` | | Structural | `relation` (links to another table), `asset_id` (references an uploaded file) | A field's **slug** and **type** are permanent once created — they are the key its values are stored under. The table's display name, description, icon and colour can change at any time; the table's slug cannot. ## Personal data and encryption [#personal-data-and-encryption] The identity field types above are treated as personal data and are automatically redacted from audit logs, whether or not the field is encrypted. A subset additionally supports **field-level encryption**: `text`, `long_text`, `email`, `phone`, `url`, `name`, `nric`, `address`, `whatsapp_id`. Note that `telegram_id` and `telegram_handle` are personal data but cannot be encrypted. When a field is created with encryption on: * Values are encrypted at rest and never returned in plaintext by default. Dashboard users and agents both see the masked form (`j***@x.com`, `+65***4567`); the real value comes back only through an explicit, audited reveal. * `text`, `long_text` and `url` have no masked form, so an agent does not see those fields at all. It can still write to them. * **The choice is permanent.** Encryption cannot be switched on or off after the field exists. ### Finding an encrypted field later [#finding-an-encrypted-field-later] An encrypted field is still findable, but only in the ways you allow. The field editor asks **Finding this field later** and offers three answers: | Choice | What a search can find | | ---------------------- | ---------------------------------------------------------------- | | **Can't be searched** | Nothing. You can still test whether a record has a value at all | | **Exact matches only** | The complete value — a whole email address, a whole phone number | | **Match any word** | The complete value, or any single word of it | Each field type arrives on the right answer, so you can usually leave this alone: * `name` → **Match any word**, so searching "Sufiyan" finds "Mohammad Sufiyan Rahmat" * `email`, `phone`, `whatsapp_id`, `nric`, `text` → **Exact matches only** * `long_text`, `url`, `address` → **Can't be searched** **Match any word** is offered on `name` and `text` only — the types whose values are made of words. It matches whole words, not fragments: "sufi" does not find "sufiyan", and there is no fuzzy matching, so "Sufyan" does not find "Sufiyan" either. Exact matching ignores capitalisation and formatting, so `User@Example.com` finds the record stored as `user@example.com`, and `+65 9123 4567` finds `+6591234567`. Two things are never available on an encrypted field, whatever you choose: **sorting** by it, and **range filters** on it (before/after, greater/less than). Like encryption itself, the choice is permanent. ## Permissions [#permissions] Access is granted per agent, per table, as four gates: **read**, **create**, **update**, **delete**. Finer control — which fields an agent can see, whether it can search all rows or only its own, export limits — is set by an admin on the table's **Permissions** tab. It cannot be changed from a conversation. Granting a gate is all an agent needs to use it. A read grant lets it find and open records, a create grant lets it add them, and so on — you do not have to give the agent a data [skill](/skills-and-tools) as well. Add a skill when you want to shape *how* it uses the table; add it for schema changes, exports and bulk imports, which are never granted this way. An agent with any read access can also inspect the table's structure — field names, types, which fields are required — so it knows what a valid record looks like before it tries to save one. This never exposes the contents of a record, and the **Allow schema inspection** checkbox lets you turn it off per table. A field an agent cannot read is also a field it cannot search. Hiding a field therefore hides it completely: the agent cannot use a search to confirm what a record holds in a column it is not allowed to see. ### Access modes [#access-modes] Read, write and delete each have an access mode: | Mode | Who it is for | | --------------------------- | ------------------------------------------------------------------------------------------------------------- | | **Self** (own records only) | Customer-facing agents — each end user only sees rows belonging to them. Requires at least one row scope rule | | **Scoped** | Internal agents limited to an admin-defined slice, e.g. one branch | | **Table** | Broad row access for trusted internal agents, still subject to field limits and per-query caps | | **Analytics** (read only) | Aggregate and count queries only; individual rows are never returned | ### Row scope rules [#row-scope-rules] A scope rule ties rows to the person currently chatting by comparing a field against the live identity of the conversation — contact ID, WhatsApp ID, Telegram ID or handle, user ID. * `contact_id` equals the current **contact ID** — matches rows created for this contact. * `whatsapp_number` equals the current **WhatsApp ID** — matches imported rows keyed by the customer's number, including rows that existed before they ever chatted. Scope rules are enforced on the server and **fail closed**: if the required identity is not available in that conversation, access is denied rather than opened up. In dashboard test chat the identity is the logged-in operator's own contact, so a WhatsApp-keyed rule only resolves there if that contact has a linked WhatsApp number. ### Scoping through a related table [#scoping-through-a-related-table] When a child table links to a parent via a `relation` field — for example `policies.client_id → clients` — the child can be scoped *through* the parent, so you do not have to copy the customer's identity onto every child row. Read the rule as: *allow a child row when its relation points at a parent row owned by the person currently chatting.* A customer asking "show my policies" has their client record found by WhatsApp number, and only policies linked to that client are returned. Constraints: * The relation must be a **single-value** relation. Multi-value relations cannot be used for scoping, and the dashboard rejects invalid configurations when you save. * When the person matches exactly one parent record, the relation is **stamped automatically** on create — the agent cannot point a row at someone else's parent record. * Matching no parent record returns zero rows, not an error. * Matching several parent records means the agent must specify which one when creating. ### Revealing an encrypted value [#revealing-an-encrypted-value] A mask is enough to recognise a record and talk about it, but not enough to phone anyone. When an agent genuinely needs the real value — to call a lead, email a quote, or confirm two records are the same person — it can reveal it, and both of these must be true: 1. The agent has the **Reveal Encrypted Field** tool, or the **Data Tables: Reveal PII** [skill](/reference/skills-catalog) that carries it. 2. The table's access settings have **Allow reveal of encrypted fields** ticked for that agent. The second switch is off on every table and every access preset until you tick it. With one of the two missing, the agent tells the person the value is available in the dashboard and stops. A reveal returns the real values for **one record** at a time, and every field it returns is written to the table's audit log with the agent that asked. Fields you have read-blocked stay blocked here — asking for the real value is not a way around a restriction you already set. Revealing is for **showing** a value, not for moving it. The agent can read it out to you, but it cannot pass it on: not into a second record, not into a message it sends, not into a connected app. Asking it to do any of those gets a refusal rather than a silent failure, so if a value needs to end up somewhere else, put it there yourself. The agent does not receive the value either — it writes its reply around a placeholder that KlicForge fills in afterwards, so what reaches the model provider is the placeholder. See [AI providers](/organization/security-and-privacy#ai-providers). Do not give this to a public widget agent, a customer-facing WhatsApp or Telegram agent, or any agent on a Self-mode table. Masking is what lets those agents be useful without holding real personal data. It is for internal operator agents — sales follow-up, support triage, back-office lookups. ## Adding records [#adding-records] Records can be created by an agent during a conversation, added manually in the dashboard, or brought in from a file — an agent can preview and import records from an attached spreadsheet. ### When a write is rejected [#when-a-write-is-rejected] A record that fails validation is reported back to the agent field by field: which field, why, and for a choice field, the values it accepts. An agent can then ask the contact one specific question rather than guessing. If it keeps failing the same write, it stops after three attempts and says what it could not do instead of retrying until it runs out of steps. Two things make rejections less likely in the first place: required fields and formats are visible to the agent before it writes, and fields the agent is not permitted to see are never named in an error. How much of the field list an error names depends on **Allow schema inspection**: with it on, a rejection lists every valid field slug; with it off, the agent is told to ask for the structure instead. This applies to single-record writes and to importing many records at once — a batch import now validates every record before writing, the same as a single one, instead of accepting a malformed record and only failing later. One rejection cannot be recovered from in the conversation: a choice field with no options set accepts no value at all. The agent is told the field needs options rather than being handed a value to guess at, and it will not create a choice field that way itself — add the options on the table's Fields tab. See [field types](/reference/data-field-types). ## Protecting personal data from the agent [#protecting-personal-data-from-the-agent] Blocking a field prevents both reading and writing it. If you want an agent to *capture* personal data but never read it back — the right default for a public-facing agent — restrict it on read only. Fields like contact name, email, phone and messaging IDs should be read-blocked on any agent the public can talk to. A read-blocked field cannot be revealed either, even on a table where reveal is allowed. ## Related pages [#related-pages] * [Tools](/skills-and-tools/tools) * [Contacts](/contacts) * [Guardrails](/guardrails) * [Security and privacy](/organization/security-and-privacy) --- title: "Create your first agent" url: "/getting-started/create-your-first-agent" description: "A detailed walkthrough of building, grounding, testing and publishing a working agent." productArea: getting-started audience: ["business-user"] tags: ["getting-started", "agents"] lastReviewed: 2026-07-28 --- # Create your first agent (/getting-started/create-your-first-agent) This walkthrough builds a customer support agent that answers questions from your own content. The same steps apply to any agent. ## Prerequisites [#prerequisites] * A KlicForge account and a workspace — see the [quickstart](/getting-started). * Some content for the agent to answer from: an FAQ, a policy document, a product sheet. A page of text is enough to start. ### Start the wizard [#start-the-wizard] Select **Agents → New Agent**. You will be offered three routes: * **Templates** — a pre-built agent for a common job, ready to adjust. * **Describe it** — write what you want in plain language and let KlicForge draft the configuration. * **Manual** — set everything yourself. For a first agent, a template is the fastest way to see how the pieces fit together. See [the creation wizard](/agents/creation-wizard) for what each route produces. ### Set the identity [#set-the-identity] Give the agent a name and description, then open the **System Prompt** tab. This is where the agent's behaviour actually lives, split across four files: | File | What it controls | | ------------ | -------------------------------------------------------- | | **IDENTITY** | Who the agent is, its role, what it will and will not do | | **SOUL** | Tone and communication style | | **AGENTS** | What it can and cannot do, in explicit terms | | **USER** | Who it is talking to, so it can pitch answers correctly | All four are optional and editable in the browser. See [core prompt files](/agents/core-prompt-files) for how to write them well. ### Attach knowledge [#attach-knowledge] Select **Knowledge Library** in the sidebar, then **New Knowledge Source**. Either paste your content directly or upload a file — PDF, Markdown, plain text, CSV, Excel, or an image. Wait for the source to finish processing, then open your agent's **Knowledge** tab and attach it. An agent with no knowledge source attached cannot answer questions about your business. This is the most common reason a new agent gives disappointing answers. ### Choose a model [#choose-a-model] On the **Model** tab, pick a model. Higher tiers reason better on harder questions. Your allowance is unaffected by the choice — [interactions](/reference/interaction-counting) are counted per turn regardless of which model answers. Temperature controls consistency. For support agents answering factual questions, keep it low (0.1–0.4). Higher values (0.5–0.8) suit conversational or creative agents. ### Set guardrails [#set-guardrails] Open the **Guardrails** tab. The default answer mode is **grounded only**, meaning the agent answers strictly from your knowledge and tool results, and says so when it cannot. That is the right default for a support agent. If you want it to handle general questions too, read [answer modes](/guardrails/answer-modes) before changing this. ### Test before publishing [#test-before-publishing] Open the agent's **Sandbox** tab and work through real questions, including ones you expect it to refuse. Check: * Does it answer from your content, not generic knowledge? * Does it admit when it does not know? * Does it stay on topic? To test systematically rather than by hand, see [evaluations](/evaluations). ### Publish [#publish] Set status to **active** on the Overview tab. Then either embed the [web widget](/channels/web-widget) on your site, or connect [Telegram](/channels/telegram) or [WhatsApp](/channels/whatsapp). ## Expected result [#expected-result] A live agent that answers from your content, refuses questions outside its scope, and is reachable on at least one channel. ## Troubleshooting [#troubleshooting] | Symptom | Likely cause | | ---------------------------------------- | ------------------------------------------------------------------------ | | Answers are vague or generic | No knowledge source attached, or the source is still processing | | Agent refuses questions it should answer | Answer mode is `grounded_only` and the content is missing from knowledge | | Agent does not respond at all | Status is `draft` or `inactive` | | Widget does not appear on your site | The site's domain is not in the agent's allowed origins | More in [troubleshooting](/troubleshooting). ## Related pages [#related-pages] * [Agents overview](/agents) * [Knowledge sources](/knowledge) * [Guardrails](/guardrails) --- title: "Finding your way around" url: "/getting-started/dashboard-navigation" description: "A map of the dashboard sidebar — what each section holds and where to find the thing you are looking for." productArea: getting-started audience: ["business-user", "developer", "admin"] tags: ["getting-started"] lastReviewed: 2026-08-25 --- # Finding your way around (/getting-started/dashboard-navigation) Everything in KlicForge is reached from the sidebar on the left of the dashboard at [app.klicforge.ai](https://app.klicforge.ai). This page is the map. There is one interface. Every feature is available to every member of your workspace, subject to your [plan limits](/reference/plan-limits) and your [role](/organization#members-and-roles) — there are no beginner and expert modes to switch between. ## The sidebar, top to bottom [#the-sidebar-top-to-bottom] | Section | What it holds | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **My Agents** | Expand it to see your agents. Select one to chat with it, the gear icon to configure it, **Create new** to add one, or **Manage agents** for the full list | | **Chats** | Your conversations with your own agents — Klic, the in-dashboard assistant, included. Expand it for recent chats or **New chat** to start one. Voice notes work here too, and the same Chats is reachable from the [Inbox app's](/conversations/inbox) Chats tab on your phone | | **Inbox** | Conversations other people are having with your agents, across every channel. The badge counts those waiting for a human | | **Knowledge Library** | Every [knowledge source](/knowledge) in the workspace | | **Data Tables** | Every [data table](/data-tables) in the workspace | | **Assets** | Every [asset](/knowledge/assets) in the workspace | | **Developer** | Everything technical — see below | | **Settings** | Workspace-level configuration. Visible to owners and admins | ## Developer [#developer] Developer is a single expandable section near the bottom of the sidebar, holding three pages: **Contacts**, **Extensions** (your custom skills and tools — see [Skills](/skills-and-tools) and [Tools](/skills-and-tools/tools)), and **Intelligence** (what KlicForge has learnt about your business from every conversation — see [Intelligence](/intelligence)), currently marked **Beta**. ## Settings [#settings] **Members**, **Workspace**, **Models**, **Integrations**, **Notifications**, **Notification Bot**, **Subscription**, **Usage** (interactions consumed this month against your allowance), **Affiliate**, and **Privacy & Compliance**. Settings appears only for owners and admins. Members work in the rest of the sidebar. ## Things worth knowing [#things-worth-knowing] * **Sections remember their state.** Expand Developer once and it stays expanded next time you sign in, on that browser. Navigating into a page inside a collapsed section expands it for you. * **Collapse the sidebar** to an icon rail when you want the screen back. Developer flattens to its individual icons there, because a nested menu does not fit. * **Agent settings live on the agent, not in Settings.** Open an agent from **My Agents** and use its tabs — Skills, Tools, Widget, Evaluations, Settings. New to KlicForge? [Create your first agent](/getting-started/create-your-first-agent) walks through the sidebar in the order you will actually use it. ## Related pages [#related-pages] * [Quickstart](/getting-started) * [Agents](/agents) * [Workspace](/organization) --- title: "Quickstart" url: "/getting-started" description: "Sign up, create an agent, test it and put it on your website — the short version." productArea: getting-started audience: ["business-user"] tags: ["getting-started"] lastReviewed: 2026-08-25 --- # Quickstart (/getting-started) KlicForge is a hosted platform — there is nothing to install. Everything happens in the dashboard at [app.klicforge.ai](https://app.klicforge.ai). ## Prerequisites [#prerequisites] * An email address you can receive mail at. * A website you can add a script tag to, if you want to embed the chat widget. ### Create an account [#create-an-account] Sign up at [app.klicforge.ai](https://app.klicforge.ai) and verify your email address. You will be asked to name your workspace — this is what owns your agents, contacts and billing. ### Create an agent [#create-an-agent] Open **My Agents** in the sidebar, then select **Create new**. You can start from a template, describe what you want in your own words, or configure everything manually. See [the creation wizard](/agents/creation-wizard) for the differences. ### Give it something to know [#give-it-something-to-know] Open the agent's **Knowledge** tab and attach a knowledge source, or create one under **Knowledge Library** in the sidebar and paste or upload your content. Without knowledge, a default agent has very little to answer from — see [knowledge sources](/knowledge). ### Test it [#test-it] Open the agent's **Sandbox** tab, or use the preview on the agent's **Widget** tab. Ask the questions your real users will ask. If answers are wrong or too vague, the usual cause is missing knowledge rather than the wrong model. ### Publish it [#publish-it] Set the agent's status to **active** on its Overview tab, then copy the embed snippet from the **Widget** tab into your site's HTML. See [the web widget](/channels/web-widget). ## What next [#what-next] * Get your bearings with the [dashboard map](/getting-started/dashboard-navigation). * Connect [Telegram](/channels/telegram) or [WhatsApp](/channels/whatsapp) so people can reach your agent where they already are. * Set up [guardrails](/guardrails) to control what the agent will and will not discuss. * Understand [how usage is counted](/reference/interaction-counting) before you go live. Building your first agent properly takes about twenty minutes. [Create your first agent](/getting-started/create-your-first-agent) walks through the same steps in detail. --- title: "Evaluations" url: "/evaluations" description: "Test an agent's quality before customers see it — suites, test cases, scoring, and publish gates." productArea: evaluations audience: ["business-user", "admin"] tags: ["evaluations", "testing"] lastReviewed: 2026-08-11 --- # Evaluations (/evaluations) Evaluations let you test an agent before it reaches your customers. You build a **suite** of **test cases** — scripted conversations with expectations — and run them against a frozen snapshot of the agent's configuration. Every response is scored automatically, and results show which cases passed, which failed, and why. Evaluations are available on **every plan**. Plan limits apply to how many suites, cases and daily runs you get. Evaluation runs happen in a sandbox. The agent's real side-effect tools — email, WhatsApp, notifications, scheduled tasks — are blocked or answered with fixtures, so a test run can never message a real customer or change live data. ## Where to find it [#where-to-find-it] Open an agent and select the **Evaluations** tab. | Sub-view | Purpose | | ---------------- | --------------------------------------------------------------- | | **Suites** | Create suites, add cases, launch runs | | **Runs** | Run history, per-case scores, turn-by-turn traces, human review | | **Publish gate** | A policy that warns or blocks when scores are too low | ## Suites and cases [#suites-and-cases] A **suite** groups related cases for one agent, such as "Refund policy accuracy". Each **case** has: * **Turns** — the scripted user messages, in order. * **Objective checks** — rule-based pass/fail, with no AI involved and no extra interaction cost: * **Required facts** — text that must appear * **Forbidden claims** — text that must never appear * **Required tool calls** — each entry asserts the tool was called; optionally it must also match specific arguments (partially or exactly) and be called at least (or at most) a given number of times * **Forbidden tool calls** — tools the agent must never call * **Required call order** — tools must be called in a given order, not necessarily back-to-back * **Maximum tool calls** — a total budget across the whole case, so an agent that loops or over-fetches fails even when every individual call is allowed * **Expected knowledge sources** the answer should be grounded in * **Maximum latency** and **maximum response length**. A case scored by the AI judge waits on an extra scoring pass, so leaving **Maximum latency** blank on one gives it a more forgiving default cap rather than no cap at all. Set a value to override it. * **AI judge** — a **reference answer and rubric** the judge scores the response against. Filling either adds one interaction per case execution. A separate **Check knowledge faithfulness** tick-box has an AI check verify the answer only asserts what the retrieved knowledge supports; it also adds one interaction per case execution and is scored n/a when nothing was retrieved. * **Severity** — low, medium, high or critical. Critical failures are highlighted and can block publishing. * **Tags** — free-form grouping, such as `happy-path` or `security`. The tags already used in the suite are offered as suggestions. * **Test setup** — optionally freeze the case's runtime context so time-dependent behaviour ("remind me tomorrow at 9") stays deterministic across reruns: a **simulated time**, entered as wall-clock time in a chosen **timezone**, and a simulated **channel**. Test setup is also where you pick which of the suite's fixtures the case runs against — see [fixtures](#fixtures) below. Only a **forbidden tool call** counts as a critical safety breach. Argument, count and order misses are correctness failures — they lower the tool-correctness score and can fail the case, but they never flag it as a safety violation. Cases are **versioned**: editing one creates a new version, so past runs still reference the exact definition they were scored against. Each case row in the suite view shows a strip of dots for its last few runs, oldest to newest, colour-coded pass/fail/critical, with a relative "last run" time — so a case that's flaky or has just started failing stands out without opening it. You can also draft a case **from a real conversation**. The user turns are lifted into a case and the customer's email addresses and phone numbers are replaced automatically with sample values — realistic ones, such as `sarah@example.com`, so the case still runs the way the original conversation did. Nothing the customer actually wrote in those fields is kept, and no message is sent to a sample address: evaluations never deliver email, WhatsApp or SMS. ## Fixtures [#fixtures] A **fixture** is a canned response for one tool, defined per suite. When the agent calls that tool during a run, the fixture's response is returned instead of executing the real tool — so a case can exercise "create the order, then confirm it" without ever writing real data. Each fixture has: * **Name** — an optional label, such as "Order not found". It is shown in place of the tool id in the suite's fixture list and in the per-case picker, which is what makes two fixtures on the same tool tellable apart. It is only a label: matching never depends on it. * **Tool** — picked from a searchable catalog, grouped into write tools (blocked by default in evaluations), the tools of any [connected app](/skills-and-tools) the agent has access to (always blocked — see below), and read tools (which already run for real). You can also type an exact tool id, which is what to do for a custom tool or when a connected app's authorisation has lapsed and its tools are temporarily missing from the list. * **Match mode** — when the fixture applies: * **Any call** to the tool * **Partial** — every field in the matcher must equal the call's arguments; extra arguments are ignored * **Exact** — the call's arguments must equal the matcher exactly * **Matcher** — the argument shape to match, as JSON. The chosen tool's field names appear as clickable keys that insert into the matcher, and the editor rejects field names the tool doesn't accept. * **Response** — the JSON body the agent receives when the fixture matches. It is prefilled with the tool's real example payload, so shaping a realistic response starts from a working template. By default every fixture in the suite applies to every case. A case can narrow this under **Test data & tool responses** in its **Test setup** by ticking only the fixtures it uses. Ticking a fixture only supplies the simulated result if the agent calls that tool — it doesn't require the call. To assert the call happens, add a required tool call under the case's objective checks. When a side-effecting tool is called and **no fixture matches**, the case's fallback (also set in **Test setup**) decides what happens: the call is **blocked** (the default), answered with a generic **safe default**, or the item is marked unsupported. Read-only tools always run for real, so retrieval and data lookups behave like production. ### Connected apps always need a fixture [#connected-apps-always-need-a-fixture] Tools that come from a connected app — Google Calendar, DocuWare, anything reached over MCP — are the one exception to all of the above. They are **always** blocked during a run without a fixture: reads included, and whatever the case's fallback is set to. A real call would reach live data in somebody else's system, and the app's own description of which of its calls are safe to repeat is not something we can verify, so nothing is taken on trust. In practice that means a case has to cover every connected-app call it will make, not just the final one. Booking an appointment usually needs a fixture for the calendar lookup that comes first as well as for the booking itself — without the first, the agent never reaches the second, and the case fails on a missing fixture rather than on the behaviour you were testing. These fixtures have no example payload to start from, since the response shape belongs to the other system rather than to KlicForge. Copy the shape from a real response where you can — inventing field names produces a case that passes against a payload the agent will never actually see. ### Reading a run's trace [#reading-a-runs-trace] Each tool call in a run's trace is badged so you can see exactly what happened: **sim** for a fixture response, **blocked** when nothing matched — and the detail distinguishes "no fixture exists for this tool" from "a fixture exists but its matcher didn't fire", so a case-authoring gap never reads as an agent failure. Expanding a call shows its arguments and result as syntax-highlighted JSON. A **blocked** badge is clickable. It opens the fixture editor with the tool and the call's real arguments already filled in, so the usual fix for a blocked call is to click it, paste a realistic response, save, and re-run. ## Scoring [#scoring] Each case is scored by a mix of deterministic checks and an optional AI judge: | Evaluator | Checks | | ---------------------- | ------------------------------------------------------------------------------------------ | | Task success | Required facts present, forbidden claims absent | | Tool correctness | Required tools called with matching arguments, counts and order; a forbidden call critical | | Knowledge grounding | The expected knowledge sources were actually retrieved | | Knowledge faithfulness | The answer only asserts what the retrieved knowledge supports (opt-in) | | Latency | The slowest turn is within the cap (judged cases default to a more forgiving one) | | Reliability | No turn errored | | Conciseness | Final response within the length cap | | AI judge | A rubric-based quality score | Knowledge grounding and knowledge faithfulness answer different questions. Grounding asks whether retrieval found the right sources; faithfulness reads the answer and asks whether it stuck to what those sources actually say. An agent can score 100% on grounding and still invent details, so the two are scored separately. Faithfulness is skipped (scored "n/a") when nothing was retrieved — that failure is grounding's to report. A case that lists no evaluators runs **all** of them, except the two that cost an extra interaction: the AI judge runs only when you supply a rubric or reference answer, and knowledge faithfulness only when you tick it on. Scores are weighted per case and aggregated into a run-level overall score, pass rate and critical-failure count. Results also group the dimensions into three at-a-glance tiers — **execution** (right tools, right arguments, no errors, in budget), **factual** (task completion, grounding and faithfulness) and **quality** (tone, conciseness, judge verdict) — so you can see whether a low score means the agent is malfunctioning or merely wordy. The grouping is display-only; it never changes the underlying score. When an item doesn't complete, its badge tells you why without conflating it with agent quality: a **test configuration error** (a missing fixture, snapshot or attachment — fix the case, not the agent) is shown differently from an **infrastructure error** or a cancellation. ## Running an evaluation [#running-an-evaluation] 1. In **Suites**, select a suite and choose **Run evaluation**. 2. The **estimate dialog** shows the exact cost before anything is charged, checked against your remaining monthly allowance. 3. Confirm. Items run in the background and results appear under **Runs**, each showing its overall score and flagging any critical failure without needing to be opened. ### Running one case [#running-one-case] Select the run icon on a case row to run that case on its own. It runs once against the current configuration, with no baseline comparison, and starts immediately — there is no estimate dialog, so nothing shows you the cost first. It still draws on your monthly allowance, so check the cost rule below before running an expensive case repeatedly. It does not use one of your daily evaluation runs. ### What a run costs [#what-a-run-costs] Evaluations draw on the same monthly allowance as chat: * **1 interaction per simulated user turn**, plus 1 per attachment on that turn * **plus 1 interaction per case that uses the AI judge**, per execution * **plus 1 interaction per case with the knowledge faithfulness check ticked**, per execution So a single-turn case with the judge costs 2 interactions. A case using only deterministic checks costs no judge interaction. See [interaction counting](/reference/interaction-counting). ## Comparing against a baseline [#comparing-against-a-baseline] On higher plans you can run a suite against both the current configuration and an earlier snapshot, producing a regression matrix showing exactly what improved and what got worse. You can also repeat each case several times to measure consistency. ## Human review [#human-review] On any finished run item, owners and admins can record a verdict — pass, fail or needs work — optionally overriding an evaluator's score, with notes. Human review sits alongside the automated result and never overwrites it. ## Reviewing a run with the assistant [#reviewing-a-run-with-the-assistant] Once a run has finished you can ask the [in-dashboard assistant](/troubleshooting/support#in-dashboard-assistant) how it went — "how did the last evaluation go?", "why is my agent failing these cases?" — instead of reading the results yourself. It can find a suite's or an agent's recent runs, report the overall result and each case's scores, and open a single case to show its per-dimension scores, the AI judge's reasoning, and any human review recorded against it. Reading results is free: no interactions are charged. Where a case fails, the assistant separates the two causes and acts differently on each: * **The agent answered badly on a fair test** — it proposes a [change set](/agents#editing-with-the-assistant) against the agent, which you approve or discard like any other. * **The test case itself was wrong** — an unrealistic expectation, a stale reference answer, a fixture it never ticked — it revises the case for you. That saves a new version of the case, so earlier runs keep the definition they were scored against, and the correction only counts from the next run onwards. When it can't tell which of the two is at fault, it says so rather than guessing. It cannot start a run, so re-running the suite to confirm a fix is still yours to do. The assistant can start from a real conversation the same way, not only a finished run — see [ask the assistant to diagnose it](/conversations#ask-the-assistant-to-diagnose-it). ## Publish gates [#publish-gates] A publish gate is a per-agent policy checked at the moment a change reaches production. | Mode | Behaviour | | ----------------- | ------------------------------------------------- | | **Informational** | Results shown, never intervenes | | **Warn** | Publishing succeeds, failing thresholds are shown | | **Block** | Publishing is refused until thresholds pass | Thresholds cover minimum overall score, maximum regressions, zero critical failures, and requiring that the evaluated snapshot matches the configuration going live. For an agent **without** [versioning](/agents/versioning) the gate applies at **activation**; with versioning it applies at each **publish**. Editing an already-active agent is never blocked — only the moment a change reaches production is gated. Rollback is never blocked either; it is the emergency path, and the verdict is reported for information only. ## Snapshots [#snapshots] Every run pins a snapshot of the agent's full configuration, so results stay reproducible after the agent changes. Knowledge **index content** is not versioned — re-embedding a source after a snapshot can change retrieval when you rerun it. A drift badge indicates when this has happened. ## Plan limits [#plan-limits] | Plan | Suites | Cases per suite | Runs per day | Baseline and repetitions | | ---------- | --------- | --------------- | ------------ | ------------------------ | | Starter | 1 | 2 | 10 | — | | Startup | 3 | 5 | 25 | — | | Growth | 10 | 15 | 100 | — | | Business | 25 | 30 | 500 | ✓ | | Enterprise | Unlimited | Unlimited | Unlimited | ✓ | Suite limits count **active** suites across the workspace; case limits count active cases per suite. Archiving frees a slot. One run counts as one per day, and a cancelled run gives the slot back. Running a single case does not use a daily slot — it still draws on your monthly interaction allowance. ## Deleting suites and cases [#deleting-suites-and-cases] Owners and admins can delete a suite or an individual case. Deletion is permanent and takes the run history with it: deleting a case also removes that case's results from past runs (run-level totals are kept). If a run is currently in progress, deletion is refused until it finishes or is cancelled. Past interaction charges are unaffected. If you only want to free a plan slot, archive instead — archived suites and cases keep their history. ## Related pages [#related-pages] * [Agent versioning](/agents/versioning) * [Interaction counting](/reference/interaction-counting) * [Guardrails](/guardrails) --- title: "Answer modes" url: "/guardrails/answer-modes" description: "The four settings controlling where an agent is allowed to source its answers, and how to choose between them." productArea: guardrails audience: ["business-user"] tags: ["guardrails"] lastReviewed: 2026-07-28 --- # Answer modes (/guardrails/answer-modes) Answer mode is the single most important guardrail setting. It decides where an agent is allowed to get its answers from. Set it on the agent's **Guardrails** tab. The default is **grounded only**. ## The four modes [#the-four-modes] ### Grounded only (default) [#grounded-only-default] The agent answers strictly from retrieved [knowledge](/knowledge) and confirmed tool results. If neither contains the answer, it says so rather than guessing. Use for: customer support, policy questions, anything where a wrong answer is costly. ### Grounded with limited inference [#grounded-with-limited-inference] As above, plus safe logical inference from what it retrieved. The agent must distinguish what came directly from a source and what it worked out. Use for: internal assistants, and cases where a strictly literal answer is unhelpfully narrow. ### Tools only [#tools-only] The agent answers exclusively from tool output. Knowledge sources are not used as an answer source. Use for: agents whose whole job is looking things up in a live system — order status, account balance, stock levels. In this mode, attaching knowledge sources will not make the agent answer from them. If your agent seems to be ignoring its knowledge, check whether this mode is selected. ### General knowledge allowed [#general-knowledge-allowed] The agent may draw on the model's own general knowledge as well. It must still attribute what is grounded versus general, and must never fabricate specific facts or statistics. Use for: general assistants, educational agents, anything conversational where being unable to answer common questions would be frustrating. ## Choosing [#choosing] | If you want the agent to… | Use | | -------------------------------------- | ------------------------------- | | Never say anything not in your content | Grounded only | | Reason a little from your content | Grounded with limited inference | | Only report what a live system says | Tools only | | Behave like a general assistant too | General knowledge allowed | ## The tradeoff [#the-tradeoff] Stricter modes produce fewer wrong answers and more "I don't know" responses. Looser modes answer more questions and carry more risk of a confident, wrong answer. If your agent refuses too much, the fix is usually **more knowledge**, not a looser answer mode. Check what it is failing to answer, add that content to a knowledge source, and test again. ## Related pages [#related-pages] * [Guardrails overview](/guardrails) * [Knowledge sources](/knowledge) * [Evaluations](/evaluations) --- title: "Guardrails" url: "/guardrails" description: "Per-agent safety controls enforced by the runtime — what each setting does, and which ones you cannot turn off." productArea: guardrails audience: ["business-user", "admin"] tags: ["guardrails", "safety"] lastReviewed: 2026-08-17 --- # Guardrails (/guardrails) Guardrails are safety controls enforced by the KlicForge runtime — not merely suggestions in the prompt. They scan input before it reaches the model, validate output before it is returned, and enforce tool policy throughout. Configure them per agent on the **Guardrails** tab. ## How a request flows [#how-a-request-flows] ```text User message → injection scan → PII redaction ↓ knowledge retrieval → chunk injection scan ↓ prompt files + guardrail rules ↓ model call ↓ response validation → safe fallback if needed ↓ guardrail events logged ``` ## What you can change [#what-you-can-change] These are the settings that are genuinely yours to configure. | Setting | Default | What it does | | --------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------- | | **Answer mode** | `grounded_only` | Where the agent may source answers from. See [answer modes](/guardrails/answer-modes) | | **Allowed topics** | empty | Topics the agent may discuss. Empty means no restriction | | **Off-topic message** | a default | What the agent says when a question is out of scope | | **PII redaction** | **on** | Removes email, phone, card and similar patterns from the message before the model sees it | | **Prompt injection checking** | on | Scans messages, knowledge passages and tool output for injection attempts | | **Tool argument validation** | on | Validates arguments against a tool's schema before running it | | **Response validation** | **off** | Runs pattern validation on every response before returning it | | **Safe fallback on validation failure** | **off** | Replaces a failing response with a safe message instead of returning it | | **Child-safe mode** | **on** | Injects strict content moderation. Turn off only for agents explicitly aimed at adult audiences | | **Tool error classification** | on | Stops the agent inventing a successful outcome when a tool fails, and retries transient errors | | **Log guardrail events** | on | Emits structured events for observability | | **Include source provenance** | off | Adds knowledge source IDs to response metadata | **PII redaction is on by default.** That means personal data in a user's message is masked before the model sees it. If your agent legitimately needs to act on what the user typed — "my email is X, please update it" — you will need to account for this when designing the flow. **Child-safe mode is on by default**, not off. It is an opt-out, not an opt-in. Leave it on unless you have a specific reason. ## What you cannot turn off [#what-you-cannot-turn-off] These are enforced for every agent regardless of configuration: * Guardrails themselves cannot be disabled. * **Topic boundary enforcement** — keeps the agent inside its defined scope. This constrains nothing while **Allowed topics** is empty, which is why the topic list above is yours to set even though the enforcement itself is not. * **Capability boundary enforcement** — blocks responses claiming abilities the agent does not have. * **Tool allowlist enforcement** — rejects calls to tools not enabled on the agent. * **No fake tool usage** — blocks responses claiming a tool ran when none did. * **Prompt leak protection** — stops system prompt content appearing in replies. * **Secret leak protection** — stops credentials and keys appearing in replies. * **Reasoning leak protection** — stops a model's internal reasoning appearing in a reply. See [reasoning effort](/agents/models#reasoning-effort). * **Tool output as data only** — strips instruction-like patterns from tool output. * **Hallucination prevention** and **no fabrication**. ## Safe fallback messages [#safe-fallback-messages] When safe fallback is enabled and a response fails validation, the agent returns one of: * *"I do not have enough verified information in my available knowledge or tools to answer that."* * *"I cannot perform that action with my current capabilities."* * *"I was unable to generate a verified response. Please rephrase your question or contact support."* ## Choosing settings [#choosing-settings] For a **public-facing support agent**: keep the defaults. `grounded_only`, PII redaction on, child-safe mode on. Consider enabling response validation and safe fallback for extra caution. For an **internal assistant**: `grounded_with_limited_inference` is often more useful, and you may want to relax topic boundaries. For an agent that **must never guess**: `grounded_only` plus response validation and safe fallback. ## Related pages [#related-pages] * [Answer modes](/guardrails/answer-modes) * [Knowledge sources](/knowledge) * [Tools](/skills-and-tools/tools) * [Security and privacy](/organization/security-and-privacy) --- title: "Intelligence" url: "/intelligence" description: "What KlicForge automatically learns about your business from every conversation — extracted events, a self-building vocabulary, and what still needs review." productArea: intelligence audience: ["business-user", "admin"] tags: ["intelligence"] lastReviewed: 2026-08-30 --- # Intelligence (/intelligence) With Business Intelligence turned on for an agent, every conversation is read for things worth tracking — an enquiry, an order, a complaint — and turned into a structured event. Over time those events also teach KlicForge the vocabulary of your business: the things customers ask about, the actions that happen to them, and the ways you slice a number. That vocabulary is the **Business Brain**. Find it under **Developer → Intelligence** in the sidebar — it's currently marked **Beta**. It is available on every plan and requires no setup — there is no business domain to pick first. ## Turning it on [#turning-it-on] Open an agent's **Settings** tab and switch on **Business intelligence**. A [business domain](/agents/domain-packs) is optional here — attaching one gives extraction a head start, but KlicForge discovers your vocabulary from your own conversations either way. ## The four tabs [#the-four-tabs] | Tab | What it shows | | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Overview** | Events extracted today, this week and this month, and how many are pending review | | **Brain** | The vocabulary KlicForge has learnt — see below | | **Events** | Every extracted event, searchable by type and filterable by type, category, date and outcome — each one shows its agent, contact and labels, with a link back to the conversation it came from | | **Audit** | Just the events still pending your review | ### What each event records [#what-each-event-records] Every event is stored in three parts, and the difference matters when you come to count things: * **What happened** — a `thing.action` type like `order.confirmed` or `task.created`, plus an **outcome** saying whether it actually happened, was only wanted, or was dropped. That outcome is what makes "enquiries that became orders" a question you can ask. * **Labels you can group by** — short reusable business words such as `product: nasi ambeng` or `topic: insurance`. These are the dimensions the Brain counts, and they are shown as chips you can click to filter the list. * **The detail** — the wording of the specific request, held encrypted and shown on the event itself rather than counted. A task's actual wording lives here, and in the agent's memory of that person, not in the labels. Every event's agent and contact are links — click either to open that agent or that contact. ## The Business Brain [#the-business-brain] The Brain groups what it has learnt into three kinds: | Kind | What it is | Example | | -------------- | ------------------------------- | --------------------------------------- | | **Things** | What customers talk about | "menu" in an event typed `menu.enquiry` | | **Actions** | What happens to a thing | "enquiry" in `menu.enquiry` | | **Dimensions** | The ways you can slice a number | product, location, topic | A **Names** section lists specific recurring values underneath those — a product, a place, a service — once the same value has come up across at least three different customers. Everything on this page is discovered automatically; nothing is created here. What you can do is correct it: **Rename** a term that came out slightly wrong, **Hide** one that should not have been promoted, or **Restore** one you hid by mistake. Renaming and hiding are owner/admin actions — a rename changes the vocabulary every metric and future extraction is expressed in. Members see the Brain read-only. A term only appears once it has been observed across at least 3 conversations, 3 different contacts and 2 days. Until then the Brain shows **Still learning**. The 3-contact threshold also keeps a single customer's own name from ever becoming a permanent business entity — a tutor's or agent's name can clear it, a customer's cannot. Identifiers — email, phone, NRIC/FIN, credit card, IP address — are never promoted into the Brain's plain vocabulary, even if a value would otherwise qualify. A rejected value is not lost; it stays in the encrypted event record, just outside anything groupable or searchable by name. ## One customer's own repeats [#one-customers-own-repeats] The Brain is deliberately about your business as a whole, which is why a value needs three different customers before it appears there. That threshold is what stops a single person's details becoming permanent company vocabulary — but it also means the Brain is the wrong place to notice that *one* customer keeps choosing the same thing. That view lives on the contact instead. The same dimensions the Brain counts across everybody are also counted per person, and surface under **Contacts → (contact) → Memory → Patterns** — "booked Marina Bay Sands 3 times". Strong enough repeats become something the agent knows about them on the next conversation. Nothing about the thresholds above changes: a value seen for one customer only still never reaches the Brain. See [Patterns](/memory#patterns). ## Populating the Brain [#populating-the-brain] A nightly job reviews recently-extracted events and curates the vocabulary from them — new terms appear, and existing ones are reinforced or, eventually, retired if nothing recent uses them. There is nothing to run by hand; a quiet workspace simply takes longer to build one up. ## Rebuilding from past conversations [#rebuilding-from-past-conversations] Conversations are read for events once, when they end — so turning Business Intelligence on does not reach back over history. **Rebuild** on the Intelligence page re-reads every ended conversation in the workspace and regenerates the events from them. You can rebuild business intelligence, [memory](/memory#rebuilding-a-contacts-memory), or both. Rebuilding both together costs the same as either one alone, because they share a single pass over each conversation. Before anything runs you are shown how many conversations will be re-read and what that costs. A rebuild costs **1 interaction per conversation**, and is blocked rather than run if it would exceed your remaining monthly allowance. Once it starts, a banner tracks how many conversations have been re-read so far and stays visible if you navigate away and come back. Events you have rejected or corrected on the Audit tab are preserved, but a rebuild may surface similar events again. Re-check the Audit queue once it finishes. Available to **owners and admins**. Your curated vocabulary in the Business Brain — renames, merges and anything you deprecated — is untouched; only the underlying events are regenerated, and the nightly job re-derives the counts from them. ## Related pages [#related-pages] * [Agents overview](/agents#memory-and-intelligence) * [Domain packs](/agents/domain-packs) * [Memory](/memory) * [Patterns](/memory#patterns) --- title: "Assets" url: "/knowledge/assets" description: "Private, reusable files an agent can find and send in chat, distinct from knowledge sources used for grounding answers." productArea: knowledge audience: ["business-user"] tags: ["assets"] lastReviewed: 2026-08-27 --- # Assets (/knowledge/assets) Assets are private, reusable files — QR codes, brochures, menus, forms, and similar media — held in your workspace's asset library and granted to specific agents to discover and send in chat. Unlike a [knowledge source](/knowledge), which is chunked and retrieved as text to ground an answer, an asset is delivered as-is — the agent sends the actual file, or a short-lived signed link, to the end user. For example: "send me the PayNow QR code." Assets reach the library three ways: you upload them, an agent generates an image during a conversation, or a customer sends a file in chat and the agent keeps it. All three belong to your workspace and count toward your storage. What differs is who an agent may offer them to — see [which conversations an asset appears in](#which-conversations-an-asset-appears-in). ## Managing assets [#managing-assets] From **Assets** in the dashboard sidebar: * **Browse the library** — see every asset with its category, file type, and status. The default **Library** view shows files you uploaded. Switch to **Generated** for images your agents produced, or **All** to see everything together. Generated images are kept out of the default view because they accumulate quickly and would otherwise bury your curated files. * **Upload a file** — select **Upload Asset**, pick a file (images, QR codes, PDFs, and other supported types up to 1 MB), and set a name, description, category, and tags. * **Edit or archive** — update an asset's metadata, archive it to hide it from active listings (reversible), or delete it permanently. * **Grant agent access** — on an asset's **Permissions** tab, grant or revoke a specific agent's read and send access. Access is deny-by-default — an agent sees nothing until it is explicitly granted. ## Which conversations an asset appears in [#which-conversations-an-asset-appears-in] A grant says which agent may use a file. Separately, each asset records which conversations it may appear in — so a file that belongs to one customer is never offered to another. | Where it came from | Who the agent can offer it to | | --------------------------------------- | -------------------------------------------------- | | You uploaded it to the library | Anyone the agent talks to | | An agent generated it in a conversation | The customer it was made for, or that conversation | | A customer sent it in chat | That customer, or the conversation they sent it in | Which of the two applies depends on how the customer reached you. On WhatsApp and Telegram the platform tells us who is writing, so the file stays with that customer and they can still ask for it in a later conversation. On the website widget anyone can type any email address, so we treat the file as belonging to **that conversation** rather than to the person — it is available for the rest of that chat, and not afterwards. That is deliberate: it is the only way to be sure one visitor cannot see another's files by guessing their email. This is enforced on the server on every attempt. It is not affected by the grant: an agent with full access to an asset still only offers it in the conversations above. To turn a generated image or a customer's file into a reusable workspace file, open it and select **Share with all conversations**. Owners and admins can do this; share only files that are genuinely reusable and contain nothing personal. You can take a shared file back out of circulation at any time with **Restrict to internal only** — agents stop offering it in chat, while it stays in your library and still counts toward storage. What sharing cannot undo is the link to the customer it came from: once a file is shared it is no longer tied to anyone, so restricting it makes it internal rather than returning it to that customer. If the customer an asset belongs to is deleted, the file stays in your library and keeps counting toward storage, but agents stop offering it in chat. ## Agent permissions [#agent-permissions] Every grant is scoped to one agent and has two independent flags: | Flag | Meaning | | ---- | ------------------------------------------------------------------------------------------------ | | Read | The agent can see the asset's metadata — name, description, category — in listings and searches. | | Send | The agent can deliver the file to a user through the current channel. | There is no implicit inheritance. An agent with read but not send access can tell a user the file exists but cannot send it; access checks happen server-side on every attempt, not only at grant time. ## Uploading from chat [#uploading-from-chat] An asset does not have to come from the dashboard — an agent with the right tools can persist a file a user just sent in the conversation, such as a payment-proof screenshot, directly as a durable asset, without a separate upload step. The file is kept to that customer, so a document one person sends is never offered to another. ## Generated images [#generated-images] When an agent generates an image, it is kept in the library so the agent can send it again later in the same conversation, and so the file is accounted for rather than expiring. Two things follow: * **Generated images count toward your workspace storage** and stay until you delete them. * **The library name describes the picture, not the request.** What the customer actually typed stays in the conversation, where access is restricted to owners and admins and every view is recorded — it is not copied onto the file where the whole team would see it. ## Linking an asset to knowledge [#linking-an-asset-to-knowledge] An asset backed by a real file can also be indexed as a knowledge source — useful when the same uploaded document should be both sendable as a file and searchable as grounding content. Enable this from the asset's detail view; the two records share the underlying stored file. ## Access logs [#access-logs] Every view, link generation, send, upload, and delete against an asset is logged with the acting agent (if any), channel, and timestamp, visible from the asset's detail view for auditing who accessed what and when. Signed links for assets are short-lived by design. If a user needs a link again later, generate a fresh one rather than reusing an old link from earlier in the conversation. ## Related pages [#related-pages] * [Knowledge sources](/knowledge) --- title: "Import a website as knowledge" url: "/knowledge/import-a-website" description: "Scan a website for free, choose how many pages to bring in, and review every generated document before it becomes agent knowledge." productArea: knowledge audience: ["business-user"] plan: startup tags: ["knowledge", "website"] lastReviewed: 2026-08-22 --- # Import a website as knowledge (/knowledge/import-a-website) Point KlicForge at a website and it reads the pages, writes a set of knowledge documents from what it found, and lets you review each one before anything becomes agent knowledge. It is one of three ways to create a [knowledge source](/knowledge), alongside writing content directly and uploading files. ## Scanning a website [#scanning-a-website] From **Knowledge Library**, select **Add Source → Import a website**, enter the site's address, and select **Scan website**. The scan finds the site's pages and reports how many there are, without importing anything or costing you anything — you always see the size and price of an import before you commit to it. By default it stays on the site's main domain and skips blog and news pages; both are toggles you can turn on before scanning if you want them included. ## Choosing how many pages to import [#choosing-how-many-pages-to-import] After a scan, pick how many pages to bring in — KlicForge suggests round numbers (10, 25, 50, 100) based on the site's size and your remaining monthly allowance, or you can import every page found. Whatever you choose is the most you can be charged; pages the site fails to return are never charged. Select **Start import** to begin. KlicForge reads the selected pages and organizes them into documents — this takes a few minutes for a large site. A scan is only good for 24 hours. If you wait longer than that before starting the import, scan the site again. ## What gets imported — and what doesn't [#what-gets-imported--and-what-doesnt] | Included by default | Excluded | | ------------------------------------------------ | ---------------------------------------------------------------- | | The homepage, always | Cart, checkout, login, search and other transactional pages | | Ordinary content pages on the site's main domain | Subdomains — turn on **Allow subdomains** to include them | | | Blog and news pages — turn on **Include blog** to include them | | | Linked PDFs and other documents — use **Upload Files** for these | Only one import can be running for a given website at a time — scanning a site that already has an import in progress is blocked until it finishes. ## Reviewing before it becomes knowledge [#reviewing-before-it-becomes-knowledge] Once KlicForge finishes organizing what it read, each generated document appears as a **draft** for you to review — nothing is searchable by an agent yet. For each one you can: * **Edit** its title, content, category or tags before deciding. * **Add** it, which turns it into a real knowledge source. * **Discard** it, which throws it away. You can also add or discard everything at once. Discarding is final — getting a document back means running the import again. Documents created this way are treated as ordinary knowledge — visible to any agent you grant the source to, including public-facing ones. Review content before adding it if the site has pages you would not want an agent repeating. If the documents don't look right — topics grouped oddly, or split in a way that doesn't match how you'd expect to search for them — edit the ones worth keeping, discard the rest, and import the site again if you still need what you threw away. A fresh import reads the pages again, so it is charged again; edit before you discard where you can. ## Importing the same site again [#importing-the-same-site-again] Sites change, so you can re-import one you have already brought in. KlicForge compares what it just read against the documents your earlier import produced for that same site, and tells you what each one will do before you decide: | Label | What it means | | ------------------------------- | ----------------------------------------------------------------------------- | | *(no label)* | Nothing like it exists yet — **Add** creates a new document | | **Updates “…”** | It matches one you already have — **Update** refreshes that document in place | | **Unchanged since last import** | The page has not changed — **Dismiss** it, there is nothing to write | | **You edited “…”** | You changed that document yourself after importing it | Updating refreshes the existing document rather than adding a second copy of it, so agents already granted that knowledge keep working and your library does not fill up with near-identical pages. **Add All** applies every recommendation in one go. Where you have edited a document yourself, KlicForge never overwrites it silently — you choose **Keep mine** or **Use new version**, and **Add All** leaves those for you rather than deciding. Documents from the earlier import that nothing matched this time are listed under **No longer on the site**. They are not removed automatically: a page missing from one crawl may simply not have been reached. Remove them yourself once you are sure. A re-import reads and charges for the pages again — the comparison happens after the pages are read, so it saves you a cluttered knowledge library rather than interactions. ## What you're billed for [#what-youre-billed-for] Scanning a site, choosing a page count, and reviewing documents are all free. You are charged **one interaction per page actually imported** — pages that fail to load, get skipped, or turn out to be duplicates of a page you already have are never charged. See [interaction counting](/reference/interaction-counting#scheduled-tasks-evaluations-website-imports-and-demo-links) for the full billing rules and worked examples. ## Related pages [#related-pages] * [Knowledge sources](/knowledge) * [Interaction counting](/reference/interaction-counting) --- title: "Knowledge sources" url: "/knowledge" description: "Ground your agent's answers in your own documents — creating sources, uploading files, and choosing how content is retrieved." productArea: knowledge audience: ["business-user"] tags: ["knowledge", "rag"] lastReviewed: 2026-08-25 --- # Knowledge sources (/knowledge) A knowledge source is a collection of content your agent can retrieve from. When someone sends a message, KlicForge searches the attached sources, pulls the most relevant passages, and gives them to the model before it answers. This is what makes an agent answer from *your* content rather than from what the model happens to know. ## Creating a knowledge source [#creating-a-knowledge-source] Select **Knowledge Library** in the sidebar, then **New Knowledge Source**. You can either: * **Write or paste content** directly in the dashboard. It is stored in the database and is available to agents immediately. * **Upload a file** and let KlicForge extract and index it. Attach it to an agent when you [create the agent](/agents/creation-wizard), or ask the [in-dashboard assistant](/troubleshooting/support#in-dashboard-assistant) to attach it to an existing one — "add the Returns Policy source to this agent." A source that is not attached to an agent is never retrieved. ## Source types [#source-types] | Type | Description | | ------------ | ------------------------------------------------------------------- | | `db-content` | Content stored in the database, written and edited in the dashboard | | `file-docs` | Content stored as files on the platform, read-only in the dashboard | Both use the same retrieval interface and can be mixed on one agent. ## Retrieval modes [#retrieval-modes] Each source has a retrieval mode that decides how content is matched to a question. | Mode | How it works | Best for | | ------------ | ----------------------------------------------------------------- | ------------------------------------------------------------ | | **Keyword** | Scores passages by word overlap with the question | Small collections, straightforward FAQ content | | **Semantic** | Uses embeddings to find related meaning even when wording differs | Larger collections, synonym-heavy content, nuanced questions | | **Hybrid** | Combines both and merges the results | Production use where precision and recall both matter | Sources created in the dashboard start on keyword search and move to hybrid automatically once their content finishes processing. A source still processing answers from keywords alone. Whichever mode a source uses, passages that are only weakly related to the question are dropped before the agent sees them. Retrieving nothing is better than retrieving something off-topic — an agent given an unrelated passage tends to answer from it. ## Granting access [#granting-access] An agent retrieves only from the sources it has been granted, chosen at creation or added afterward by asking the assistant. You can grant them individually, by category, or all at once — an agent granted a whole category picks up sources added to that category later, without revisiting the agent. When a search covers several sources, results come back from each of them rather than filling up on whichever source scores highest. ## Uploading files [#uploading-files] ### Supported file types [#supported-file-types] | Category | Types | | ------------ | ------------------------------------------------------ | | Documents | PDF | | Text | `.txt`, `.md` | | Spreadsheets | CSV, Excel (`.xlsx`, `.xls`) — rendered as tables | | Images | JPEG, PNG, GIF, WebP — text extracted by OCR or vision | **File size limit:** 30 MB per file. Your plan's limits on number of sources and total storage are checked before an upload is accepted. ### How upload works [#how-upload-works] 1. Choose **Upload a file** when creating a source. 2. The file uploads directly to secure storage. 3. An ingestion job runs automatically; the source shows a live status. 4. When status reaches **completed**, it is ready to attach to an agent. ### The ingestion pipeline [#the-ingestion-pipeline] Each file goes through **detect → extract → clean → chunk → embed**: * **Detect** — classifies the document and picks an extraction strategy. * **Extract** — PDFs use text extraction, with OCR for scanned pages; visual-heavy PDFs use vision extraction. Spreadsheets become tables. Images use OCR or vision. * **Clean** — removes OCR noise. Already-structured formats skip this. * **Chunk and embed** — content is split and indexed for retrieval. ### Limits worth knowing [#limits-worth-knowing] * **Vision page cap** — vision extraction processes the first 50 pages by default; later pages are skipped with a warning. * **Empty extraction is rejected** — if no text can be pulled out, the upload fails rather than creating an empty source. * **Ingestion uses tokens** — cleanup and vision extraction consume tokens recorded against your workspace's usage. You can reprocess an uploaded source from its detail view, which is useful if you want to force a different extraction strategy. ## Contact-scoped knowledge [#contact-scoped-knowledge] A knowledge source can be classified so that it belongs to a single contact rather than the whole workspace. A contact-owned source is only retrievable in conversations with that contact, which is how you give one customer access to their own documents without exposing them to everyone. Classification controls retrieval. Review it before uploading anything containing personal or customer-specific information. ## Troubleshooting retrieval [#troubleshooting-retrieval] | Symptom | Likely cause | | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- | | Agent says it does not know something in your document | Source not attached to the agent, or still processing | | A keyword source finds nothing for a question your document covers | The question shares no distinctive words with the source — switch it to hybrid so wording differences stop mattering | | Answers cite the wrong passage | Try hybrid retrieval, or split a large document into focused sources | | Upload rejected | Unsupported file type, over 30 MB, or no extractable text | | Scanned PDF returns nothing useful | Reprocess and force vision extraction | | Agent ignores knowledge entirely | Check [answer mode](/guardrails/answer-modes) is not `tools_only` | ## Related pages [#related-pages] * [Agents overview](/agents) * [Guardrails](/guardrails) * [Troubleshooting](/troubleshooting) * [Import a website](/knowledge/import-a-website) * [Assets](/knowledge/assets) --- title: "Marketplace" url: "/marketplace" description: "Browse and install agent templates, built-in skills and built-in tools without leaving the page you're on." productArea: marketplace audience: ["business-user"] tags: ["marketplace", "agents", "skills", "tools"] lastReviewed: 2026-08-22 --- # Marketplace (/marketplace) The **Marketplace** is one place to browse everything KlicForge ships out of the box — agent [templates](/agents/templates), built-in [skills](/skills-and-tools), and built-in [tools](/skills-and-tools/tools) — and install any of them straight into your workspace. Marketplace is the read-only catalog. Your own custom skills and tools — the ones you author yourself — live in [Extensions](/skills-and-tools), not here. ## Browsing [#browsing] Select **Marketplace** in the sidebar. The home page shows featured and recently updated listings, and you can: * **Search** across agents, skills and tools at once. * **Filter by type** — agents, skills, or tools. * **Browse by category** — customer support, sales, messaging, scheduling, research, content, data, and more. Each category page lists everything in it, filterable by type. Every listing has its own detail page with a description, what it includes, and — for skills and tools — which agents already use it. An agent template's detail page shows its four [core prompt files](/agents/core-prompt-files) — IDENTITY, SOUL, AGENTS and USER — as separate sections, each with what it covers, so you know what you're installing before you do. Built-in tools are listed as capability groups rather than one card per action — all of a connected integration's actions (WhatsApp messaging, Gmail, and so on) appear as a single listing. Open it to see the individual actions inside. A group that needs a one-time connection says so on its detail page; connect it from **Settings → Integrations** first. ## Installing [#installing] What **Install** does depends on the listing type: * **Install Agent** — opens the [agent creation wizard](/agents/creation-wizard) with that template already selected, exactly as if you had picked it from **Agents → New Agent → Templates**. Nothing is created until you finish the wizard. * **Install Skill** / **Install Tool** — choose which of your agents should get it. It's attached immediately — the same write as toggling it on from that agent's **Capabilities** tab — and you land there to see it enabled. There is no separate installed/not-installed state to manage: platform skills and built-in tools are always available to every workspace. Installing just attaches one to an agent, which you can undo any time from that agent's Capabilities tab. ## Related pages [#related-pages] * [Skills](/skills-and-tools) * [Tools](/skills-and-tools/tools) * [Agent templates](/agents/templates) * [Agents overview](/agents) --- title: "Memory" url: "/memory" description: "How an agent remembers a contact across conversations, what has to be enabled first, and how to manage what is stored." productArea: memory audience: ["business-user", "admin"] plan: startup tags: ["memory"] lastReviewed: 2026-08-30 --- # Memory (/memory) With memory enabled, an agent remembers durable facts about a contact between conversations — preferences, stated facts, events — and uses the relevant ones on future turns. A returning customer does not have to repeat themselves. Without memory, every conversation starts fresh. ## Three things must be true [#three-things-must-be-true] Memory only runs when **all three** are in place. Turning on just one is not enough. 1. **Your plan includes it.** Memory is available from the **Startup** plan upwards. See [plans and limits](/organization). 2. **The agent has memory enabled** — the agent's **Settings** tab, under Intelligence Layer. 3. **The conversation is not excluded** — some channels or sessions can opt out, which is how `/reset` on [Telegram](/channels/telegram) starts a genuinely clean conversation. ## Set a business domain first [#set-a-business-domain-first] Before memory can be switched on, the agent needs a **business domain** selected in Settings. Memory extraction is domain-aware: the domain tells KlicForge what kinds of facts, entities and events are worth remembering for your business. Until a domain is chosen, the memory toggle stays locked. ## How it works [#how-it-works] Memory is **batch-driven, not per-turn**, which keeps its cost predictable: * A conversation is queued for extraction only once it **ends** — either explicitly, or when it goes idle long enough to expire. * A background job reads ended conversations, extracts durable facts, and marks them so they are not processed twice. * Long-lived channels like Telegram and the widget enter the queue when their conversation expires on idle. This means a fact a customer mentions will not be available in the *same* conversation's later turns as a memory — it is already in the conversation history for that. It becomes memory for *next* time. The whole conversation is read, however long it ran, so something stated in the opening turns is weighed the same as something stated at the end. ## What can be remembered [#what-can-be-remembered] A fact is only kept when it can be traced to the customer's own words. Every fact carries a quote, and that quote is checked against the conversation transcript before the fact is stored. Anything that cannot be matched is discarded rather than saved with a guess attached. The agent's own replies never count as evidence. If your agent summarises back — "so you are relocating in March" — that sentence cannot become a remembered fact on its own; the customer has to have said it. The practical effect is fewer remembered facts per conversation than an unchecked extraction would produce, and far less chance of a fact nobody stated. There is one deliberate exception, and it is labelled as one — see [Patterns](#patterns) below. ## Time and dates [#time-and-dates] Every remembered fact is dated, and anything with a time of its own — an appointment, a delivery, a deadline — also records **when it happens**, not just when it was mentioned. Two things follow from that: * **Relative wording is resolved when the fact is stored.** A customer saying "lunch tomorrow at 11" is remembered as the actual date, so it still reads correctly weeks later. * **Something that has already happened is marked as past**, and the agent weighs it far lower than a stable fact or an upcoming one. A past appointment can still be recalled if a customer asks about it — it just will not be offered as though it were still ahead. Where a customer never gave a specific time — "I still need to do the grocery run" — the agent records only when they last raised it, and treats it as stale once it has not come up for a while. It will not present it as something still scheduled. Preferences and stable facts do not fade this way. "Prefers email" stays as relevant a year on; last month's appointment does not. If a date is wrong, correct it on the fact itself in **Contacts → (contact) → Memory** — the **Occurs on** field. Clear it for a fact that has no date of its own. ## Patterns [#patterns] Some things a customer never says out loud. Somebody who has booked the same hotel on three separate trips has a preference, but they may never have put it in words — so nothing in the rules above would ever capture it, because there is no sentence to quote. **Patterns** are the exception. They are not extracted from what was said; they are counted from what happened. If [Business Intelligence](/intelligence) is on for the agent, every conversation already produces structured events — a booking, an order, an enquiry — and each one records the things it was about. When the same value comes up again and again for one contact, that repetition is the pattern. Open **Contacts → (contact) → Memory** and choose the **Patterns** view: > **hotel** > Marina Bay Sands — seen 3 times across 3 conversations A value has to come up **at least 3 times** to appear. Two is a coincidence. ### When a pattern becomes something the agent knows [#when-a-pattern-becomes-something-the-agent-knows] Showing you a pattern and telling the agent about it are two different bars, and the second one is higher. A pattern is promoted into an actual remembered preference overnight, once it has come up **3 or more times across at least 2 separate conversations**. Three mentions inside a single conversation is one story told at length, not a habit — so it stays on the Patterns view and goes no further. A promoted pattern reads as a plain sentence with the arithmetic left in: > Repeatedly chooses Marina Bay Sands for hotel (3 of 4 bookings). The fraction matters. "3 of 4" says the customer chose something else once; it does not claim more consistency than the record shows. The agent is always told that a pattern was **inferred from repeated behaviour, not stated** — so it can use it to make a suggestion without ever claiming the customer said it. That distinction is the whole reason patterns are kept separate from ordinary remembered facts. ### What this needs, and what it costs [#what-this-needs-and-what-it-costs] * **Business Intelligence must be on** for the agent, or there are no events to count and the Patterns view stays empty. The view itself works on every plan. * **There must be something on the events to count.** A pattern is a repeated [label](/intelligence#what-each-event-records) — a hotel, a product, a topic — so the Patterns view only fills up as fast as your events carry labels worth repeating. Attaching a [business domain](/agents/domain-packs) that fits your work is the single biggest thing you can do here: it tells extraction which labels each kind of event should record. * **Promotion into memory follows the memory rules** — the same three conditions above, so an agent with memory switched off never gains a pattern, on any plan below Startup. * **No extra interactions.** Counting is a database query and the sentence is assembled from the numbers, with no model involved. Patterns cost nothing on top of the events you already have. A promoted pattern appears alongside everything else on the contact's Memory page, and can be edited or removed there like any other remembered fact — and the decision sticks. Reword the sentence and the nightly count keeps your wording; archive it and it is not recreated, even if the customer repeats the behaviour. If the customer later states the preference outright, the stated version takes over. ## What the agent has to hand [#what-the-agent-has-to-hand] The agent always carries a short profile of the person it is talking to — durable things like their name, their role, and how they prefer to be contacted, plus any promoted [patterns](#patterns). That is what makes a returning customer feel recognised from the first message. A stated preference outranks an inferred one when there is only room for a few, so something the customer actually told you is never crowded out by something counted from their behaviour. Everything else — past appointments, errands, previous orders — is looked up only when it is relevant, so an ordinary question is not answered through a pile of old detail. Ask about something specific ("what did I order last time?") and the agent goes and finds it. ## Corrections [#corrections] When a customer changes something they told you earlier — a time moved, a figure revised — the newer version replaces the older one, and the old version is kept as superseded rather than sitting alongside the new one as a contradiction. ## Scopes [#scopes] Each remembered fact has a scope: | Scope | Meaning | | --------- | ----------------------------------- | | Workspace | Applies to every agent and contact | | Contact | Belongs to one [contact](/contacts) | | Session | Limited to a single conversation | ## Managing what is stored [#managing-what-is-stored] Admins can view and edit what an agent remembers about someone from **Contacts → (contact) → Memory**: individual facts and when each one happens, how they relate to each other, session summaries, a searchable graph, and the [patterns](#patterns) counted from their past events. The graph has a search box to find a node by name, and its legend doubles as a filter — click a kind to hide every node of it, and click again to bring it back. Memory stores what customers tell your agent. Review it before enabling memory on an agent that handles sensitive information, and remember that a contact's memory is part of what you must produce or delete if they exercise a data request. ## Rebuilding a contact's memory [#rebuilding-a-contacts-memory] Memory is built once per conversation, when that conversation ends. If memory was switched on after a contact's conversations had already happened, or older memories were captured before recent accuracy improvements, **Rebuild memory** on the contact's Memory page re-reads their past conversations and regenerates what the agent knows about them. Before anything runs you are shown how many conversations will be re-read and what that costs. A rebuild costs **1 interaction per conversation**, and is blocked rather than run if it would exceed your remaining monthly allowance. Old memories are **archived, not deleted** — including the people, companies and products your agents have identified, which are re-created from the same conversations rather than left as they were. That's what lets a rebuild clear out a duplicate or mis-identified entity. Any connection already drawn to an archived entity stops rendering until re-extraction reconnects it to the fresh copy. New memories appear over the following minutes as the rebuild progresses — a banner tracks how many conversations have been re-read so far and stays visible if you navigate away and come back. Clicking Rebuild twice does nothing the second time and costs nothing — conversations already queued for a rebuild are not counted again. Available to **owners and admins**. ## Cost [#cost] Extraction uses a model, and that usage is billed to your workspace. The per-agent toggle is the real cost control — only agents with memory on cause any extraction at all. A long conversation costs more to extract than a short one, because it is read in full rather than sampled. ## Related pages [#related-pages] * [Contacts](/contacts) * [Agents overview](/agents) * [Plans and usage](/organization) --- title: "Affiliate program" url: "/organization/affiliate" description: "How the KlicForge referral program pays recurring commissions, and how to join." productArea: organization audience: ["business-user", "admin"] tags: ["affiliate", "referrals", "billing"] lastReviewed: 2026-08-01 --- # Affiliate program (/organization/affiliate) KlicForge runs a referral-based affiliate program. Enrolled affiliates earn recurring commissions on every paid invoice from workspaces they refer, for up to 12 months from the referred workspace's first payment. * **You earn** — up to 15% commission on each paid invoice, calculated on the net amount after payment processing fees. * **They save** — 10% off their first invoice through your referral link or promo code. ## Joining [#joining] 1. Sign in to the KlicForge dashboard. 2. Go to **Settings → Affiliate**. 3. Select **Join the program** — enrollment is instant. 4. Copy your referral link or share your promo code. Your referral link is `https://klicforge.ai/r/YOURCODE`. Referred visitors can also enter your code at checkout. ## Commission schedule [#commission-schedule] Rates vary by the referred workspace's plan and billing cycle: | Plan | Monthly billing | Yearly billing | | -------- | --------------- | -------------- | | Startup | 10% | 12% | | Growth | 12% | 14% | | Business | 15% | 15% | Commissions are calculated on the net invoice amount (gross minus payment processing fees), not the gross amount. The rate is fixed at the time each commission accrues — later changes to the commission schedule do not retroactively alter existing commissions. ## Eligibility window [#eligibility-window] * Commissions accrue for **12 months** from the referred workspace's first paid invoice. * The window is set once and is not extended by plan changes, cancellations, or resubscriptions. * If a referred workspace resubscribes after its eligibility window has expired, no new commissions accrue. ## Payout hold period [#payout-hold-period] Commissions are held for **30 days** from the invoice date before becoming eligible for payout, covering the standard refund and chargeback dispute window. The payable-from date is shown against each commission in your dashboard. ## Cancellation clawback [#cancellation-clawback] If a referred workspace cancels within **90 days** of its first paid invoice, any pending or approved commissions for that referral are voided. This reflects the early-churn risk period. ## Refunds and chargebacks [#refunds-and-chargebacks] * A refunded invoice automatically reverses the matching commission. * A charged-back payment automatically reverses the matching commission. * If a reversal happens after a commission has already been paid out, the amount may be deducted from a future payout. ## Commission statuses [#commission-statuses] | Status | Meaning | | ----------- | ----------------------------------------------------------------------------- | | Pending | Accrued; waiting for the 30-day hold period before payout eligibility | | Approved | Hold period passed; eligible for payout in the next settlement | | Paid | Included in a completed payout | | Clawed back | Reversed due to a refund or chargeback | | Void | Cancelled — typically because the referred workspace cancelled within 90 days | | Rejected | Manually rejected, for example after a self-referral is detected | ## Payouts [#payouts] Payouts are currently processed manually: 1. Confirm you have approved commissions in your dashboard. 2. Email [hello@klicforge.ai](mailto:hello@klicforge.ai) with your payout request. 3. Provide accurate payee details and any required tax documentation, such as a W-9 or W-8BEN. KlicForge may withhold payouts pending identity verification or to investigate suspected abuse. ## Self-referral policy [#self-referral-policy] You may not refer your own workspace, any workspace you own or control, or any account where the billing party is materially the same person or entity as you. This is enforced at both the workspace and individual level. Violations result in commission forfeiture and may lead to program termination. ## Changing your referral code [#changing-your-referral-code] You may change your referral code to a custom code once. Your previous code stays active and attributable for any visitors who received it before the change, but cannot be reissued or reused by anyone else. ## Tracking [#tracking] All referrals and commission details are visible in **Settings → Affiliate**. The commissions table shows status, invoice amount, commission amount, and — for commissions still in the hold period — the date they become payable. ## Related pages [#related-pages] * [Workspace](/organization) * [Fair use policy](/organization/fair-use-policy) --- title: "Fair use policy" url: "/organization/fair-use-policy" description: "How KlicForge protects platform stability on a shared platform, and what happens if usage is unusually high." productArea: organization audience: ["business-user", "admin"] tags: ["fair-use", "billing"] lastReviewed: 2026-08-01 --- # Fair use policy (/organization/fair-use-policy) KlicForge plans are designed for normal business usage. To keep the platform reliable for everyone, KlicForge applies internal safeguards to detect unusually high, abusive, automated, runaway, or resource-intensive usage. Most workspaces never encounter these safeguards. Usage is evaluated on overall platform consumption rather than message count alone — different models, knowledge retrieval, memory, workflow executions, integrations, and tools consume different amounts of platform resources. If sustained usage significantly exceeds what is typical for your plan, KlicForge may reach out to discuss a more suitable plan or arrangement. ## How the safeguards work [#how-the-safeguards-work] KlicForge is a shared platform. The safeguards exist to protect service quality for everyone while staying out of your way during ordinary use: * Normal business usage does not trigger any safeguard. * Unusually high, automated, or runaway usage may be temporarily limited to protect platform stability. * You do not need to track or manage usage yourself — KlicForge handles this for you. * Sustained high-volume needs are best served by a Business or Enterprise plan. ## Abuse and suspension [#abuse-and-suspension] KlicForge reserves the right to suspend an account if it detects abuse, including: * Deliberate circumvention of usage controls or resource safeguards * Resource exhaustion attacks * Unauthorized service reselling * Malicious use such as spam, scraping, or phishing For suspected abuse, KlicForge typically issues a warning before suspension. Suspended accounts can appeal by emailing [support@klicforge.ai](mailto:support@klicforge.ai). ## High-volume and enterprise needs [#high-volume-and-enterprise-needs] If your use case calls for sustained high-volume usage, large-scale automation, advanced AI workloads, or business-critical deployments, contact sales at [hello@klicforge.ai](mailto:hello@klicforge.ai). KlicForge can recommend a plan upgrade or set up a custom enterprise arrangement. ## Plan features [#plan-features] Each plan includes a defined set of features — number of agents, monthly interaction allowances, knowledge sources, channels, and team members. These are published plan features, separate from the fair-use safeguards on this page. See the [plan limits reference](/reference/plan-limits) and the [pricing page](https://klicforge.ai/pricing) for the current comparison. ## Frequently asked questions [#frequently-asked-questions] **Are there token limits?** KlicForge does not publish exact token budgets. Fair-use safeguards apply instead. Normal business usage will not hit them; very high-volume or automated usage may require a Business or Enterprise plan. **Why does AI usage vary?** Usage depends on agent complexity, the tools and integrations an agent uses, knowledge retrieval, memory, workflow steps, model routing, and conversation length. You do not need to track tokens yourself. **What happens if my usage is unusually high?** KlicForge may apply temporary safeguards or reach out to discuss your needs. Enterprise and custom plans are available for sustained high-volume usage. ## Policy updates [#policy-updates] This policy may be updated at any time. KlicForge notifies workspaces of material changes by email and updates this page. Continued use of KlicForge after a policy change constitutes acceptance of the new terms. ## Related pages [#related-pages] * [Plan limits](/reference/plan-limits) * [Interaction counting](/reference/interaction-counting) * [Workspace](/organization) --- title: "Workspace" url: "/organization" description: "Members and roles, plans and limits, usage tracking, and the security controls available to administrators." productArea: organization audience: ["admin"] tags: ["organization", "billing", "plans"] lastReviewed: 2026-08-25 --- # Workspace (/organization) Your workspace owns your agents, contacts, data and billing. You created one when you signed up, and your personal account can belong to several. ## Members and roles [#members-and-roles] Invite people from **Settings → Members**. There are three roles: | Role | Can do | | ---------- | -------------------------------------------------------- | | **Owner** | Everything, including billing and transferring ownership | | **Admin** | Manage agents, data, contacts and members | | **Member** | Work with agents and conversations | The number of members you can have is a plan limit. ## Plans and limits [#plans-and-limits] Every allowance — agents, interactions, storage, team members, evaluation limits and how many agent versions are kept — is listed in the [plan limits reference](/reference/plan-limits). That page is generated from the platform's own plan configuration, so it cannot drift from what is actually enforced. The free plan is called **Starter**. Prices and the current feature-by-plan breakdown are on the [pricing page](https://klicforge.ai/pricing) — that page is the authority on what costs what. Some features are only available from a certain plan, including WhatsApp, [agent versioning](/agents/versioning), [memory](/memory), and custom skills and tools. The pricing page lists which. ## Usage [#usage] Open **Settings → Usage** in the dashboard to see interactions consumed this month, what is left, and a breakdown by agent. Allowances reset at the start of each calendar month. Read [interaction counting](/reference/interaction-counting) to understand exactly what is counted — it is not one per message. ## Billing [#billing] Owners manage the subscription from **Settings → Subscription**: change plan, update payment details, and see invoice history. * **Upgrading** takes effect immediately and is prorated. * **Downgrading** takes effect at the end of the current billing period, so you keep what you paid for. ## Security [#security] * Personal data in contacts and data tables is encrypted at rest. * Channel credentials and tool auth headers are write-only — stored encrypted, never returned. * Actions on personal data are recorded in an audit log, with the data itself redacted. * Administrators of the platform are subject to mandatory multi-factor authentication. Read [security and privacy](/organization/security-and-privacy) for what is held, how long it is kept, which AI providers see your conversations, and what you are responsible for. ## Data export and deletion [#data-export-and-deletion] You can export everything held about a [contact](/contacts), which is what a right-of-access request needs. Deletion requests are handled through the same area. ## Related pages [#related-pages] * [Security and privacy](/organization/security-and-privacy) * [Fair use policy](/organization/fair-use-policy) * [Notifications](/organization/notifications) * [Affiliate program](/organization/affiliate) * [Interaction counting](/reference/interaction-counting) * [Contacts](/contacts) * [Agent versioning](/agents/versioning) --- title: "Notifications" url: "/organization/notifications" description: "Alert your own team when something happens in KlicForge, across inbox, email, webhook, web push, Telegram and Slack." productArea: organization audience: ["business-user", "admin"] tags: ["notifications", "operations"] lastReviewed: 2026-08-19 --- # Notifications (/organization/notifications) Notifications alert **your team** — operators, admins, billed contacts — when something happens in KlicForge: a new contact is captured, a conversation starts or ends, an agent escalates to a human, usage approaches a quota, a billing event occurs, or a scheduled task runs. Notifications deliver to **your team**. [Channels](/channels) deliver agent messages to **your end users** — the two are separate systems. Notifications are available on all plans. Configure them from **Settings → Notifications**. ## Notification channels [#notification-channels] | Channel | Delivers to | | ----------------- | ------------------------------------- | | Inbox | In-app dashboard, per workspace | | Email | Workspace members or billed contacts | | Webhook | An external HTTPS endpoint | | Web push | A member's browser, desktop or mobile | | Operator Telegram | A specific verified team member | | Slack | A channel in your Slack workspace | ### Inbox [#inbox] The notification inbox is the in-app hub — a singleton per workspace, created automatically on first use, tracking read and unread state per member. Inbox entries can optionally fan out to web push. The bell icon showing this feed is in both the dashboard and the [KlicForge Inbox](/conversations/inbox) mobile app, so a missed push alert is never the only way to see it. ### Email [#email] Email notifications go to active members of the workspace. Configure from **Settings → Notifications → Add Channel → Email** and enter the recipient address. ### Webhook [#webhook] Webhook notifications POST a JSON payload to your endpoint, signed with HMAC-SHA256. Only HTTPS endpoints are accepted; private and loopback addresses are rejected. The default delivery timeout is 5 seconds. Configure from **Settings → Notifications → Add Channel → Webhook**. ### Web push [#web-push] Web push delivers browser notifications to a member's desktop or mobile browser. Select **Enable Web Push** in notification settings — each member subscribes their own browser individually. If you belong to more than one workspace, subscribing once covers all of them: the browser is registered against every workspace you are a member of, and an alert says which one it came from when you open it. Leaving a workspace stops its alerts reaching you without affecting the rest. Turning notifications off on a device removes it from every workspace at once. ### Operator Telegram [#operator-telegram] Operators receive alerts in Telegram through a workspace-wide notification bot paired with a per-member verified identity: 1. Go to **Settings → Notification Bot** and connect the bot with a bot token. 2. Each operator completes a `/verify` flow with the bot in Telegram, linking their Telegram chat to their member identity. 3. Add a Telegram notification channel for that member from **Settings → Notifications**. Routing is per-operator, so escalation alerts reach only the intended person. ### Slack [#slack] 1. At [api.slack.com/apps](https://api.slack.com/apps), select **Create New App → From scratch**, name it, and pick your workspace. 2. Under **OAuth & Permissions**, add the bot token scopes `chat:write`, `channels:read`, and `channels:join`, then select **Install to Workspace** and copy the bot token. 3. In the dashboard, go to **Settings → Integrations**, find **Slack**, and select **Connect**. Paste the bot token. 4. Go to **Settings → Notifications**, select **Add Channel → Slack**, pick a channel from your workspace, and save — the bot joins the channel automatically. For a private Slack channel, invite the bot manually first with `/invite @your-bot-name` in that channel, then select it from the dropdown. Use **Send test** on any channel to verify delivery. You can add multiple Slack channels, each routed to different events. ## Notification events [#notification-events] * **Contacts and conversations** — a contact is captured, a conversation starts or ends * **Handoff** — an agent escalates to a human; see [escalate to human](/channels/handoff) * **Takeover follow-ups** — a conversation you're handling is reassigned, a customer replies while you have it, or an escalation goes unclaimed for too long * **Usage** — allowance reaches 70%, 90%, or 100% * **Billing** — activation, renewal, failed payment, scheduled downgrade, cancellation * **Scheduled tasks** — task lifecycle and run events * **Data tables** — a record is created, updated, or deleted ## Data table notifications [#data-table-notifications] Data table events fire whenever a record changes in any collection. Subscribe per collection and write custom content using field values as variables. 1. Go to **Settings → Notifications → Subscriptions** and select a channel. 2. Enable **Record created**, **Record updated**, or **Record deleted**. By default this applies across all collections. 3. To scope to one collection, select the collection filter icon on that subscription and choose a collection. ### Custom content [#custom-content] Each subscription can define a custom message using four optional fields — **Title**, **Heading**, **Subheading**, and **Content** — with `{{variableName}}` placeholders. Built-in variables are `{{collectionName}}`, `{{recordId}}`, `{{eventType}}`, and `{{recordUrl}}`; any field's slug is also available, for example `{{email_address}}`. Unknown variable names are left as-is. ## Security [#security] * All notification channel credentials — webhook secret, email configuration, bot token, push keys — are write-only: encrypted at rest and never shown in the dashboard after saving. * A global mute switch suppresses all dispatch without deleting channels. Toggle it under **Settings → Notifications → General**. * A delivery failure on one channel never blocks delivery to the others. ## Related pages [#related-pages] * [Channels](/channels) * [Escalate to human](/channels/handoff) * [Workspace](/organization) --- title: "Security and privacy" url: "/organization/security-and-privacy" description: "What KlicForge holds, how long it is kept, which AI providers see your conversations, and what you are responsible for as the workspace running the agent." productArea: organization audience: ["admin", "business-user"] tags: ["security", "privacy", "compliance"] lastReviewed: 2026-08-26 --- # Security and privacy (/organization/security-and-privacy) This page is for the person running a workspace on KlicForge. It covers what the platform holds on your behalf, how long it keeps it, and the settings that are yours to get right. If you are reviewing KlicForge as a vendor rather than operating it, the [Trust Hub](https://klicforge.ai/trust-hub) is the authority on our security posture, and the [Subprocessor list](https://klicforge.ai/subprocessors) on who processes what. ## What KlicForge holds [#what-klicforge-holds] Running an agent produces four kinds of data: * **Conversations** — every message between a contact and your agent, on every channel. * **[Contacts](/contacts)** — who your agent has spoken to, and whatever personal details they disclosed during a conversation. * **[Data table](/data-tables) records** — anything your agent captured into a table you defined. * **[Knowledge](/knowledge) and files** — the documents you uploaded to ground the agent, and any files a contact sent it. If [memory](/memory) is on, the platform also stores facts extracted from ended conversations so the agent can recall them later. ## Encryption and isolation [#encryption-and-isolation] * Personal data in contacts and data tables is encrypted at rest, field by field. On a data table you choose which fields are encrypted, and [the choice is permanent](/data-tables#personal-data-and-encryption). * Connections are encrypted in transit — to the API, to the dashboard, and to the database. * Channel credentials, tool authentication headers and custom-model API keys are write-only. They are stored encrypted and never returned by any endpoint, including to you. * Each workspace's data is isolated from every other workspace's, enforced both in the application and independently at the database. * Actions on personal data are recorded in an audit log, with the personal data itself redacted. ## How long data is kept [#how-long-data-is-kept] A conversation ends automatically once it has been idle for its channel's window: | Channel | Idle window | | -------------- | ----------- | | Web widget | 1 hour | | Telegram | 24 hours | | WhatsApp | 24 hours | | Dashboard chat | 8 hours | Ending a conversation does not delete it — it closes the session, so the next message starts a fresh conversation rather than resuming the old one. You can change the window per agent. Everything else follows these windows: | What | Kept for | | -------------------------- | --------------------------------------------- | | Conversations and messages | Until you delete them or close the workspace | | Contacts and table records | Until you delete them or close the workspace | | Memory | Until the contact or the workspace is deleted | | Knowledge files | Until you delete them or close the workspace | | Data audit log | 12 months | | Security audit log | 24 months | | Billing records | 7 years, as tax law requires | | Database backups | 7-day rolling window | Closing the workspace removes your agents, contacts, conversations, memory and files. Deleted data can persist in backups until the rotation window elapses. ## AI providers [#ai-providers] Your conversations are sent to a third-party model provider to generate each reply. Which provider depends on the model you selected for the agent — see the [model settings](/agents) on the agent's detail page. Every provider that can see conversation content is named on the [Subprocessor list](https://klicforge.ai/subprocessors), along with what each one states about retaining and training on the data it receives. That page is the authority; read it before choosing a model for an agent that handles sensitive information. [Revealing an encrypted field](/data-tables#revealing-an-encrypted-value) is handled differently: the model is given a placeholder rather than the value, and KlicForge substitutes the real value into the reply after the model has written it. The value is not sent to the provider at that point. It does become part of that reply, so if the conversation carries on it is included in the history sent with later messages. ## What you are responsible for [#what-you-are-responsible-for] You decide what personal data your agent collects and why. KlicForge processes it on your instructions. In practice that means: * **Yours** — telling people they are talking to an AI agent, having a lawful reason to collect what you collect, answering requests from your own contacts, and configuring the agent so it cannot disclose one person's data to another. * **Ours** — keeping the platform secure, encrypting what you store, honouring the retention windows above, and disclosing every subprocessor. The full split is in the [Privacy Policy](https://klicforge.ai/privacy-policy), and the [Data Processing Addendum](https://klicforge.ai/data-processing-addendum) is available for business customers. ## Running a safe public-facing agent [#running-a-safe-public-facing-agent] An agent on a public website talks to strangers. Before you publish one: * Keep the answer mode at **grounded only** so it answers from your knowledge rather than from the model's general training. See [answer modes](/guardrails/answer-modes). * Block the agent from **reading back** personal fields it is allowed to write, so nobody can ask it to recite someone else's details. See [protecting personal data from the agent](/data-tables#protecting-personal-data-from-the-agent). * Set [allowed topics](/guardrails#what-you-can-change) so it stays inside its job. * Restrict [allowed origins](/channels/web-widget#allowed-origins) to the domains you actually embed on. * Give the agent only the [tools](/skills-and-tools/tools) it needs. Every tool is a capability a stranger can try to reach. KlicForge checks public [web widget](/channels/web-widget) traffic for automated abuse before a session is established. That runs on every widget with nothing to configure, and it limits scripted traffic rather than replacing any of the controls above. If the agent is not meant to be public at all, set its channel to **Restricted** and list who may reach it — see [access control](/channels#access-control). Do this on Telegram or WhatsApp, where the messaging platform confirms the sender. A web widget visitor arrives with whatever identity the page supplies, so treat a widget allow list as a convenience and put anything genuinely private behind your own login. Some protections are always on and cannot be weakened — prompt-injection scanning, secret-leak protection, and tool-output-as-data-only among them. See [what you cannot turn off](/guardrails#what-you-cannot-turn-off). ## Cookies and analytics [#cookies-and-analytics] **Settings → Privacy & Compliance → Cookie preferences** records whether KlicForge may use analytics cookies while you work in the dashboard. The choice is stored once and honoured across klicforge.ai, this documentation site and the dashboard, and you can change it at any time. Refusing changes nothing about how KlicForge works — analytics cookies are not needed to use it. For visitors in the EU, EEA, UK and Switzerland nothing analytics-related starts until consent is recorded, and if the region cannot be determined none runs at all. The analytics library itself is not even downloaded until a choice is made, and refusing discards anything recorded while the choice was outstanding rather than sending it after the fact. The [cookie policy](https://klicforge.ai/cookie-policy) lists every cookie with its purpose and lifetime. This covers the dashboard and the KlicForge websites only — the chat widget you embed on your own site sets no cookies, so it does not add a consent obligation of its own. ## Data requests [#data-requests] When someone asks what you hold about them, export everything on their [contact record](/contacts#data-requests). Deletion works from the same place. A contact export includes their conversation history and their memory. Review what it contains before sending it. Requests about your own account, rather than about one of your contacts, go through the [data request page](https://klicforge.ai/data-request). Requests from your own contacts — a data access, export, correction, deletion, or opt-out request they send you directly — are managed from **Settings → Privacy & Compliance** in the dashboard. A daily automated process fulfils approved requests; the default response time is 30 days, up to 45 for complex requests. Deleting a contact is one exception: their WhatsApp marketing opt-out is kept even after the rest of their record is gone, so KlicForge does not start marketing to someone who had deliberately opted out. Transactional messages — appointment reminders, order updates, and the like — are unaffected either way. ## Compliance and regulatory alignment [#compliance-and-regulatory-alignment] KlicForge is designed to support alignment with GDPR, CCPA/CPRA, and Singapore PDPA, and to build toward SOC 2 readiness. KlicForge does not currently hold a formal certification. If you are assessing KlicForge against Singapore PDPA specifically, the [PDPA and data processing overview](https://klicforge.ai/trust-hub/pdpa) covers the data intermediary role, retention and deletion. Where a breach notification is required, the regulatory timelines are: | Regulation | Notification window | | -------------- | ------------------------------------------------------------ | | GDPR (Art. 33) | Supervisory authority notified within 72 hours of discovery | | CCPA / CPRA | Affected consumers notified within 30 days | | Singapore PDPA | PDPC notified within 3 calendar days for a notifiable breach | The [Data Processing Addendum](https://klicforge.ai/data-processing-addendum) is published as a draft for Business and Enterprise customers to review before signing up; it is not yet a counsel-approved, binding agreement. For a countersigned copy, contact [hello@klicforge.ai](mailto:hello@klicforge.ai). For a detailed look at KlicForge's security controls and subprocessor list, see the [Trust Hub](https://klicforge.ai/trust-hub) and the [Subprocessor list](https://klicforge.ai/subprocessors). ## Related pages [#related-pages] * [Workspace](/organization) * [Guardrails](/guardrails) * [Contacts](/contacts) * [Data tables](/data-tables) --- title: "Built-in tools" url: "/reference/built-in-tools" description: "The tools an agent can be given, grouped by what they act on." productArea: reference audience: ["business-user", "developer"] tags: ["tools"] lastReviewed: 2026-08-21 --- # Built-in tools (/reference/built-in-tools) {/* Generated by scripts/generate-references.ts from snapshots/klicforge-public.json. Do not edit by hand. */} KlicForge ships 92 built-in [tools](/skills-and-tools/tools). Enable the ones an agent may call on its **Tools** tab — an agent can only call tools you have explicitly enabled. Which tools are available depends on your plan and on which integrations you have connected. Tool calls do not consume extra allowance: a turn is [one interaction](/reference/interaction-counting) no matter how many tools it uses. ### General [#general] | ID | Name | What it does | | ------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `sys-calculator` | Calculator | Perform mathematical calculations including addition, subtraction, multiplication, division, powers, and square roots | | `sys-get-search` | Knowledge Search | Search the agent knowledge base for factual information, documentation, policies, pricing, or business-specific details. | | `sys-get-weather-openmeteo` | Get Weather (Open-Meteo) | Get current weather conditions using the free Open-Meteo API. Accepts a city name or latitude/longitude coordinates. No API key required. | | `sys-get-weather-weatherapi` | Get Weather (WeatherAPI) | Get current weather conditions using WeatherAPI. Accepts a city name or latitude/longitude. Requires a WeatherAPI key to be configured. | | `sys-get-web-search-brave` | Web Search (Brave) | Search the web using Brave Search. Returns relevant results for the agent to synthesise. Requires a Brave Search key to be configured. | | `sys-get-web-search-perplexity` | Web Search (Perplexity) | Search the web using Perplexity Sonar via OpenRouter. Returns a synthesised, cited answer — ideal for research tasks. Requires an OpenRouter key to be configured. | ### Data tables [#data-tables] | ID | Name | What it does | | -------------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `tenant_data.add_field` | Data: Add Field | Add a new typed field (column) to an existing data collection. | | `tenant_data.aggregate_records` | Data: Aggregate Records | Compute count, sum, avg, min, or max aggregates over records in a data table. | | `tenant_data.batch_insert_records` | Data: Batch Insert Records | Insert multiple records into a collection in one call (max 500). Use for data migration, imports, and bulk population. | | `tenant_data.create_collection` | Data: Create Collection | Create a new data table (collection) for the tenant. | | `tenant_data.create_record` | Data: Create Record | Create a new record in a data table. Requires create permission on the collection. | | `tenant_data.delete_record` | Data: Delete Record | Soft-delete a record. Requires delete permission on the collection. Destructive action. | | `tenant_data.describe_collection` | Data: Describe Collection | Get the field schema for a data table. | | `tenant_data.export_records` | Data: Export Records | Export all records from a collection to CSV, JSON, or XLSX. Returns a presigned download URL. Respects field-level permissions. | | `tenant_data.get_record` | Data: Get Record | Retrieve a single record by ID from a data table. | | `tenant_data.import_records_from_attachment` | Data: Import Records From Attachment | Bulk-import records into a collection from an attached CSV/JSON/XLSX file of any size, auto-mapping columns to field slugs. | | `tenant_data.list_collections` | Data: List Collections | List all data tables this agent has been granted access to. | | `tenant_data.preview_import_file` | Data: Preview Import File | Parse an attached CSV/JSON/XLSX file and preview its columns, sample rows, and a proposed field schema before creating a new collection from it. | | `tenant_data.reveal_field` | Data: Reveal Encrypted Field | Reveal the full values of encrypted fields on one record. Requires "Allow reveal" on the collection's access policy; every field revealed is written to the data audit log. | | `tenant_data.search_records` | Data: Search Records | Search and filter records in a data table with optional sorts and pagination. | | `tenant_data.set_agent_permission` | Data: Set Agent Permission | Grant or update an agent's read/create/update/delete access on a data collection. | | `tenant_data.update_collection` | Data: Update Collection | Rename a data table or update its description, icon, or color. Slug can't be changed. | | `tenant_data.update_field` | Data: Update Field | Update a field's name, description, required flag, or select options. | | `tenant_data.update_record` | Data: Update Record | Update fields on an existing record. Requires update permission on the collection. | ### Assets [#assets] | ID | Name | What it does | | ------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `assets.admin.archive` | Assets Admin: Archive | Archive an asset — hides it from active listings without deleting it. | | `assets.admin.delete` | Assets Admin: Delete | Permanently delete an asset and revoke all agent access to it. Destructive. | | `assets.admin.get` | Assets Admin: Get | Get full details for a single asset, including which agents have access. | | `assets.admin.list_all` | Assets Admin: List All | List every asset in the tenant’s asset library, regardless of agent grants. | | `assets.admin.remove_permission` | Assets Admin: Remove Permission | Revoke an agent’s access to an asset. | | `assets.admin.set_permission` | Assets Admin: Set Permission | Grant or update an agent’s canRead/canSend access to an asset. | | `assets.admin.update` | Assets Admin: Update | Update an asset’s name, description, category, or tags. | | `assets.admin.upload_from_attachment` | Assets Admin: Upload From Attachment | Add a new asset to the tenant’s library from the current turn’s inbound chat attachment. | | `assets.create_signed_url` | Assets: Create Signed URL | Generate a short-lived (5-15 min) signed URL for an assigned asset. | | `assets.get_metadata` | Assets: Get Metadata | Get metadata for a single assigned asset. | | `assets.list` | Assets: List | List the private files/media this agent has been granted access to. Excludes images the agent generated during conversations — use Assets: Search to find those. | | `assets.persist_upload` | Assets: Persist Inbound Attachment | Persist the current inbound chat attachment (e.g. a payment-proof screenshot) as a durable asset. | | `assets.search` | Assets: Search | Search assigned assets by name, description, tags, category, or MIME type. Also finds images generated earlier for the same person. | | `assets.send_asset` | Assets: Send Asset | Send an assigned asset directly to the user through the current channel. | ### Email [#email] | ID | Name | What it does | | ------------------- | ---------------------- | ------------------------------------------------------------------------------- | | `email.addLabel` | Email: Add Label | Add one or more labels to an email message. | | `email.archive` | Email: Archive Message | Archive an email message (removes from inbox without deleting). | | `email.createDraft` | Email: Create Draft | Create an email draft without sending it. | | `email.listDrafts` | Email: List Drafts | List email drafts in the mailbox. | | `email.listLabels` | Email: List Labels | List all Gmail labels (system and user-created). | | `email.read` | Email: Read Message | Fetch the full content of an email message including body and attachments list. | | `email.removeLabel` | Email: Remove Label | Remove one or more labels from an email message. | | `email.search` | Email: Search Messages | Search for email messages using Gmail query syntax. | | `email.send` | Email: Send Message | Compose and send an email immediately. | | `email.sendDraft` | Email: Send Draft | Send an existing draft. | | `email.updateDraft` | Email: Update Draft | Update an existing email draft with new content. | ### Contacts [#contacts] | ID | Name | What it does | | -------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------ | | `contacts.admin.create` | Contacts Admin: Create | Create a new contact record within the current tenant. | | `contacts.admin.delete` | Contacts Admin: Delete | Permanently delete a contact and its conversations within the current tenant. Destructive. | | `contacts.admin.get` | Contacts Admin: Get | Retrieve a single contact record by ID within the current tenant. | | `contacts.admin.linkChannelIdentity` | Contacts Admin: Link Channel Identity | Set a channel identity (telegramId, telegramHandle, phone, authUserId) on a contact. | | `contacts.admin.merge` | Contacts Admin: Merge | Merge duplicate contacts into a single surviving contact. Destructive. | | `contacts.admin.search` | Contacts Admin: Search | Search contacts within the current tenant. | | `contacts.admin.unlinkChannelIdentity` | Contacts Admin: Unlink Channel Identity | Clear a channel identity from a contact's record. | | `contacts.admin.update` | Contacts Admin: Update | Update fields on an existing contact within the current tenant. | | `contacts.me.delete` | My Contact: Delete | Anonymize the current user's own contact details. Conversation history is preserved. | | `contacts.me.get` | My Contact: Get | Retrieve the current user's own contact details. Never accepts a contact ID. | | `contacts.me.update` | My Contact: Update | Update the current user's own contact details (self-editable fields only). | ### WhatsApp [#whatsapp] | ID | Name | What it does | | ----------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------- | | `whatsapp.create_reply_draft` | WhatsApp: Create Reply Draft | Draft a reply for human review before sending (draft\_replies mode). | | `whatsapp.escalate_to_human` | WhatsApp: Escalate to Human | Flag the conversation for human review (refunds, complaints, complex requests). | | `whatsapp.get_conversation` | WhatsApp: Get Conversation | Get the current WhatsApp conversation context. | | `whatsapp.list_available_templates` | WhatsApp: List Available Templates | List Meta-approved WhatsApp templates this agent may send. | | `whatsapp.list_messages` | WhatsApp: List Messages | List recent inbound and outbound WhatsApp messages for this connection. | | `whatsapp.mark_conversation_status` | WhatsApp: Mark Conversation Status | Mark a WhatsApp conversation as resolved or open. | | `whatsapp.send_message` | WhatsApp: Send Message | Send a text message to the customer via WhatsApp (auto\_reply mode). | | `whatsapp.send_template` | WhatsApp: Send Template | Send a Meta-approved WhatsApp template message (bypasses the 24-hour window). | ### Knowledge [#knowledge] | ID | Name | What it does | | -------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `knowledge_base.create_source` | Knowledge Base: Create Source | Create a new knowledge base source with a name, description, and optional initial content. | | `knowledge_base.delete_source` | Knowledge Base: Delete Source | Permanently delete a knowledge base source. Destructive — confirm before calling. | | `knowledge_base.get_original_document` | Knowledge Base: Get Original Document | Get a short-lived download link for the original uploaded file behind a knowledge source — a separate, always-checked authorization from search access. | | `knowledge_base.get_source` | Knowledge Base: Get Source | Get full details of a knowledge source by ID, including its current content. | | `knowledge_base.list_sources` | Knowledge Base: List Sources | List all knowledge base sources for this tenant with their IDs, names, types, and embedding status. | | `knowledge_base.reindex_source` | Knowledge Base: Reindex Source | Trigger background vector re-indexing for a knowledge source. | | `knowledge_base.update_source` | Knowledge Base: Update Source | Replace the content of a knowledge base source and trigger reindexing. | ### DocuWare [#docuware] | ID | Name | What it does | | ------------------------------ | ----------------------------- | ------------------------------------------------------------------------------------- | | `docuware.download_document` | DocuWare: Download Document | Download the content of a DocuWare document as base64. Limited to 10 MB. | | `docuware.get_document` | DocuWare: Get Document | Retrieve metadata and index fields for a specific DocuWare document. | | `docuware.list_file_cabinets` | DocuWare: List File Cabinets | List all available DocuWare file cabinets in the organization. | | `docuware.search_documents` | DocuWare: Search Documents | Full-text and index-field search for documents within a DocuWare file cabinet. | | `docuware.trigger_workflow` | DocuWare: Trigger Workflow | Trigger a DocuWare workflow for a specific document. | | `docuware.update_index_fields` | DocuWare: Update Index Fields | Update index field values on an existing DocuWare document. | | `docuware.upload_document` | DocuWare: Upload Document | Upload a new document (base64) to a DocuWare file cabinet with optional index fields. | ### Scheduling [#scheduling] | ID | Name | What it does | | ---------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------ | | `scheduling.cancel_scheduled_task` | Scheduled Tasks: Cancel Scheduled Task | Permanently cancel a scheduled task so it no longer executes. | | `scheduling.create_scheduled_task` | Scheduled Tasks: Create Scheduled Task | Create a one-time or recurring scheduled task, reminder, or follow-up for this agent. | | `scheduling.list_scheduled_tasks` | Scheduled Tasks: List Scheduled Tasks | List scheduled tasks for this agent, optionally filtered by status. | | `scheduling.pause_scheduled_task` | Scheduled Tasks: Pause Scheduled Task | Temporarily pause a scheduled task without deleting it. | | `scheduling.resume_scheduled_task` | Scheduled Tasks: Resume Scheduled Task | Resume a paused scheduled task from the next computed run time. | | `scheduling.update_scheduled_task` | Scheduled Tasks: Update Scheduled Task | Update the title, time, recurrence rule, timezone, or instruction of an existing scheduled task. | ### Images [#images] | ID | Name | What it does | | ---------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `image.generate` | Generate Image | Generate an image from a text prompt, optionally guided by reference photos (product\_image, person\_image, style\_reference, background\_reference, composition\_reference, brand\_reference, reference\_image). Works for text-to-image and image-to-image. Uses the agent's configured image generation model. | ### Human handoff [#human-handoff] | ID | Name | What it does | | --------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `handoff.escalate_to_human` | Escalate to Human Operator | Notify the assigned human operator (a tenant member) via their connected Telegram that this conversation needs human attention. Auto-attached when the agent has Escalate to Human enabled. | ### Date & time [#date--time] | ID | Name | What it does | | -------------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | `datetime.resolve_relative_date` | Resolve Relative Date | Resolve an open-ended relative date, e.g. "the second Tuesday of next month", "in 10 business days", or "the last Friday of next month". | ### Memory [#memory] | ID | Name | What it does | | --------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `memory.search` | Search Memory | Recall what the agent remembers about this contact from past conversations — appointments, errands, past orders, and anything not in the always-on profile. Results are dated and marked past, upcoming or stale. | ## Related pages [#related-pages] * [Tools](/skills-and-tools/tools) * [Skills](/skills-and-tools) --- title: "Data table field types" url: "/reference/data-field-types" description: "Every column type a data table supports, and which can be encrypted." productArea: reference audience: ["business-user", "developer"] tags: ["data-tables"] lastReviewed: 2026-08-21 --- # Data table field types (/reference/data-field-types) {/* Generated by scripts/generate-references.ts from snapshots/klicforge-public.json. Do not edit by hand. */} Every column in a [data table](/data-tables) has a type. The type is permanent once the field is created. | Type | What it holds | Can be encrypted | Masked when encrypted | | ----------------- | ---------------------------------------------------------- | ---------------- | --------------------- | | `text` | Short single-line text. | Yes | No | | `long_text` | Multi-line text, for notes and descriptions. | Yes | No | | `number` | A number, whole or decimal. | No | No | | `currency` | A monetary amount. | No | No | | `date` | A calendar date with no time. | No | No | | `datetime` | A date and a time. | No | No | | `boolean` | True or false. | No | No | | `single_select` | One choice from a list you define. | No | No | | `multi_select` | Any number of choices from a list you define. | No | No | | `email` | An email address. | Yes | Yes | | `phone` | A telephone number. | Yes | Yes | | `url` | A web address. | Yes | No | | `status` | A workflow state, such as new, in progress or done. | No | No | | `json` | Structured data, for values that do not fit another type. | No | No | | `auto_increment` | A number that increases automatically for each new record. | No | No | | `uuid` | A unique identifier generated automatically. | No | No | | `contact_id` | A reference to the contact a record belongs to. | No | No | | `relation` | A link to a record in another table. | No | No | | `name` | A person's name. | Yes | Yes | | `nric` | A national identity number. | Yes | Yes | | `address` | A postal address. | Yes | Yes | | `whatsapp_id` | A contact's WhatsApp number. | Yes | Yes | | `telegram_id` | A contact's numeric Telegram ID. | No | No | | `telegram_handle` | A contact's Telegram username. | No | No | | `asset_id` | A reference to an uploaded file or image. | No | No | **Can be encrypted** — the field can be created with field-level encryption. That choice is permanent, and it limits how the field can be searched — by a whole value, by a whole word, or not at all. See [finding an encrypted field later](/data-tables#finding-an-encrypted-field-later). **Masked when encrypted** — values are shown partially hidden (`j***@x.com`) and revealed only through an explicit, audited action. This applies to encrypted fields; note that `telegram_id` and `telegram_handle` are treated as personal data but cannot be encrypted. ## Related pages [#related-pages] * [Data tables](/data-tables) * [Security and privacy](/organization/security-and-privacy) --- title: "Glossary" url: "/reference/glossary" description: "KlicForge terminology, including the common alternative names people search for." productArea: reference audience: ["business-user", "developer", "admin"] tags: ["glossary", "reference"] lastReviewed: 2026-08-14 --- # Glossary (/reference/glossary) Terms as KlicForge uses them. Where a term is commonly called something else, the alternatives are listed so you can find the right page. ## Agent [#agent] A configurable AI unit combining an identity, a model, skills, tools, knowledge sources and guardrails. Sometimes called a **chatbot**, **bot** or **assistant** elsewhere; KlicForge calls it an agent because it does more than chat — it can look things up and take actions. See [agents](/agents). ## Interaction [#interaction] The billing unit. One user turn is one interaction, plus one per attachment and one per file the agent sends back. Sometimes called a **message**, **credit** or **request**. Tool calls do not add to it. See [interaction counting](/reference/interaction-counting). ## Knowledge source [#knowledge-source] A collection of content an agent retrieves from to answer questions. Often called a **knowledge base**, **KB**, **document store** or **RAG source**. See [knowledge sources](/knowledge). ## Skill [#skill] A reusable block of instructions that shapes how an agent behaves. Sometimes called a **capability** or **persona**. A skill does not execute anything. See [skills](/skills-and-tools). ## Tool [#tool] A function an agent can call to fetch data or take an action. Sometimes called an **action**, **function** or **integration**. See [tools](/skills-and-tools/tools). ## Channel [#channel] Somewhere people can talk to your agent — the web widget, Telegram, WhatsApp, or the inbox. Sometimes called an **integration** or **deployment target**. See [channels](/channels). ## Access mode [#access-mode] Whether a channel is **Open** — anyone may message it — or **Restricted**, where only the allow list may. Sometimes called **public vs private** or **gated**. See [access control](/channels#access-control). ## Allow list / deny list [#allow-list--deny-list] Who may and may not reach an agent on a given channel. Sometimes called a **whitelist** and a **blacklist**. An entry is a contact, one data table row, or every row in a data table; the deny list applies in both access modes and always wins over the allow list. See [access control](/channels#access-control). ## Contact [#contact] A person who talks to one of your agents. Sometimes called a **user**, **customer**, **visitor** or **end user**. In KlicForge, "user" means someone on *your team* with a dashboard login; a contact is someone on the outside. See [contacts](/contacts). ## Data table [#data-table] Structured storage an agent can read and write during a conversation. Also called a **collection**. Comparable to a spreadsheet or a database table. See [data tables](/data-tables). ## Guardrail [#guardrail] A safety control enforced by the runtime — what an agent may discuss, where it may source answers, which tools it may call. Sometimes called **safety settings** or **policy**. See [guardrails](/guardrails). ## Answer mode [#answer-mode] The guardrail deciding where an agent may source answers from: grounded only, grounded with limited inference, tools only, or general knowledge allowed. See [answer modes](/guardrails/answer-modes). ## Memory [#memory] Durable facts an agent remembers about a contact between conversations. Distinct from conversation history, which is only within one conversation. See [memory](/memory). ## Evaluation [#evaluation] A test suite for an agent — scripted conversations with expectations, scored automatically. Sometimes called **testing**, **QA** or **regression tests**. See [evaluations](/evaluations). ## Scheduled task [#scheduled-task] A message an agent sends proactively on a schedule, rather than in reply. Sometimes called an **automation**, **campaign**, **broadcast** or **reminder**. See [scheduled tasks](/scheduled-tasks). ## Workspace [#workspace] What owns your agents, contacts, data and billing. Sometimes called an **organization**, **tenant** or **team**. Distinct from your **account**, which is your personal login — one account can belong to several workspaces. See [workspace](/organization). ## Publish / version [#publish--version] A frozen snapshot of an agent's configuration serving production, while you edit a draft. Sometimes called a **release** or **deployment**. See [agent versioning](/agents/versioning). ## Prompt files [#prompt-files] The four Markdown files defining an agent's behaviour: IDENTITY, SOUL, AGENTS and USER. Sometimes called the **system prompt**. See [core prompt files](/agents/core-prompt-files). ## Widget [#widget] The embeddable chat interface for your website. The developer package is called the **AgentKit widget SDK** — AgentKit is the name of the technical toolkit, KlicForge is the platform. See [the web widget](/channels/web-widget) and [the widget SDK](/build/widget-sdk). --- title: "Guardrail settings" url: "/reference/guardrail-settings" description: "Every guardrail an agent has, its default, and whether you can change it." productArea: reference audience: ["admin", "developer"] tags: ["guardrails", "safety"] lastReviewed: 2026-08-21 --- # Guardrail settings (/reference/guardrail-settings) {/* Generated by scripts/generate-references.ts from snapshots/klicforge-public.json. Do not edit by hand. */} Every setting on an agent's **Guardrails** tab, with its default. See [guardrails](/guardrails) for what to change and why. | Setting | Default | Configurable | What it does | | ----------------------------------- | ----------------- | ------------ | --------------------------------------------------------------------------------------------------- | | **enabled** | `true` | Always on | Master switch. Guardrails cannot be turned off. | | **answerMode** | `grounded_only` | Yes | Where the agent may source answers from. See [answer modes](/guardrails/answer-modes). | | **topicBoundaryEnforcement** | `true` | Always on | Keeps the agent within its defined scope. Constrains nothing while allowed topics is empty. | | **allowedTopics** | empty | Yes | Topics the agent may discuss. Empty means no restriction. | | **offTopicMessage** | a default message | Yes | What the agent says when a question falls outside its scope. | | **capabilityBoundaryEnforcement** | `true` | Always on | Blocks responses claiming abilities the agent does not have. | | **toolAllowlistEnforcement** | `true` | Always on | Rejects calls to tools not enabled on the agent. | | **toolArgumentValidation** | `true` | Yes | Validates tool arguments against the tool's schema before running it. | | **disallowFakeToolUsage** | `true` | Always on | Blocks responses claiming a tool ran when none did. | | **promptInjectionCheck** | `true` | Yes | Scans messages, knowledge passages and tool output for injection attempts. | | **promptLeakProtection** | `true` | Always on | Stops system prompt content appearing in replies. | | **secretLeakProtection** | `true` | Always on | Stops credentials and keys appearing in replies. | | **piiRedaction** | `true` | Yes | Removes email, phone, card and similar patterns from a message before the model sees it. | | **toolOutputTreatedAsDataOnly** | `true` | Always on | Strips instruction-like patterns from tool output, so a compromised endpoint cannot issue commands. | | **hallucinationPrevention** | `true` | Always on | Enables hallucination heuristics. | | **disallowFabrication** | `true` | Always on | Blocks responses containing fabricated information. | | **disallowFakeCitations** | `true` | Yes | Blocks responses citing sources that cannot be verified. | | **toolErrorClassification** | `true` | Yes | Stops the agent inventing a successful outcome when a tool fails, and retries transient errors. | | **responseValidation** | `false` | Yes | Runs pattern validation on every response before returning it. | | **safeFallbackOnValidationFailure** | `false` | Yes | Replaces a failing response with a safe message instead of returning it. | | **childSafeMode** | `true` | Yes | Injects strict content moderation. Turn off only for agents aimed explicitly at adult audiences. | | **logGuardrailEvents** | `true` | Yes | Emits structured guardrail events for observability. | | **includeSourceProvenance** | `false` | Yes | Adds knowledge source IDs to response metadata. | "Always on" means the control is enforced for every agent and cannot be disabled. Answer modes: `grounded_only`, `grounded_with_limited_inference`, `tools_only`, `general_knowledge_allowed`. See [answer modes](/guardrails/answer-modes). ## Related pages [#related-pages] * [Guardrails](/guardrails) * [Answer modes](/guardrails/answer-modes) --- title: "Interaction counting" url: "/reference/interaction-counting" description: "How KlicForge counts interactions against your monthly plan allowance, with worked examples." productArea: reference audience: ["business-user", "admin"] tags: ["usage", "billing", "plans"] lastReviewed: 2026-08-26 --- # Interaction counting (/reference/interaction-counting) Every KlicForge plan includes a monthly allowance of **interactions**. This page explains exactly what counts as one, so you can predict your usage. ## What counts as one interaction [#what-counts-as-one-interaction] An interaction is charged **per user turn**, not per message exchanged. One turn covers everything the agent does in response: reading its knowledge, calling tools, thinking, and writing its reply. The rule is: ```text interactions for a turn = 1 + 1 for each attachment the user sends + 1 for each file the agent sends back ``` ### What does not count [#what-does-not-count] None of the following add to your interaction count: * **Tool calls.** An agent that calls six tools to answer one question still costs one interaction. * **Retries and internal steps.** Intent detection, image analysis, transcription and conversation summaries are all part of running the platform, not separate interactions. * **Turns that never reach the model.** If a request fails before the agent responds, it is not charged. * **Agent replies on their own.** Only user turns start the count. Attachments are counted individually because each one is processed separately — an image is analysed, a document is read, a voice note is transcribed. ## Worked examples [#worked-examples] | What happened | Interactions | | ------------------------------------------------------------------------------------ | ------------ | | A visitor asks a question, the agent answers | 1 | | A visitor asks a question that makes the agent search knowledge and call three tools | 1 | | A visitor sends a message with two photos attached | 3 | | A visitor sends a voice note | 2 | | A visitor asks for a document and the agent sends one file back | 2 | | A conversation with ten back-and-forth user messages, no attachments | 10 | | Scanning a website to see how many pages it has | 0 | | Importing 25 pages from a website | 25 | ## Scheduled tasks, evaluations, website imports and demo links [#scheduled-tasks-evaluations-website-imports-and-demo-links] **Scheduled tasks** that send a message through an agent are charged the same way as a user turn. A scheduled or [audience message](/scheduled-tasks/audience-messages) that carries an [image attachment](/scheduled-tasks#attaching-an-image) costs 2 interactions instead of 1 — the same "+1 per attachment" rule as a chat turn — charged per recipient. A self-service [memory or business intelligence rebuild](/memory#rebuilding-a-contacts-memory) costs **1 interaction per conversation re-read**. Rebuilding both memory and intelligence together costs the same as rebuilding either one alone, since they share a single pass over each conversation. The dashboard shows the exact cost before you confirm, and blocks the rebuild rather than running it if it would exceed your remaining allowance. **Website imports** are charged **one interaction per page imported**. Scanning a site to see how many pages it has — and what importing them would cost — is free, so you always see the price before you commit. You choose the page limit before the import starts, and that limit is the most you can be charged. Pages the site fails to return are not charged, and turning the generated documents into knowledge costs nothing further. **Evaluations** are charged per simulated user turn, plus one interaction for each test case that uses the AI judge. A single-turn test case scored by the judge therefore costs 2 interactions. Test cases using only deterministic checks cost no judge interaction. The estimate shown before you start an evaluation run uses these same rules. **[Demo links](/channels/demo-links)** create real conversations, charged exactly like a conversation through your live widget. ## Monthly allowances [#monthly-allowances] | Plan | Interactions per month | | ---------- | ---------------------- | | Starter | 50 | | Startup | 500 | | Growth | 2,000 | | Business | 10,000 | | Enterprise | Unlimited | Allowances reset at the start of each calendar month. ## Where to check your usage [#where-to-check-your-usage] Open **Settings → Usage** in the dashboard at [app.klicforge.ai](https://app.klicforge.ai) to see interactions consumed this month, your remaining allowance, and a breakdown by agent. Owners and admins only. ## Related pages [#related-pages] * [Documentation home](/) --- title: "Plan limits" url: "/reference/plan-limits" description: "Agents, interactions, storage and other allowances included with each plan." productArea: reference audience: ["business-user", "admin"] tags: ["plans", "limits"] lastReviewed: 2026-08-21 --- # Plan limits (/reference/plan-limits) {/* Generated by scripts/generate-references.ts from snapshots/klicforge-public.json. Do not edit by hand. */} Every KlicForge plan includes the allowances below. Prices, and the current feature-by-feature breakdown, are on the [pricing page](https://klicforge.ai/pricing). | Limit | Starter | Startup | Growth | Business | Enterprise | | ---------------------------- | ------- | ------- | ------ | --------- | ---------- | | Agents | 3 | 5 | 10 | 25 | Unlimited | | Interactions per month | 50 | 500 | 2,000 | 10,000 | Unlimited | | Knowledge sources | 3 | 10 | 15 | 50 | Unlimited | | Storage | 10 MB | 250 MB | 1 GB | 5 GB | Unlimited | | Custom skills you can create | — | 3 | 10 | Unlimited | Unlimited | | Team members | 2 | 3 | 10 | 25 | 99 | | Evaluation suites | 1 | 3 | 10 | 25 | Unlimited | | Test cases per suite | 2 | 5 | 15 | 30 | Unlimited | | Evaluation runs per day | 10 | 25 | 100 | 500 | Unlimited | | Agent versions kept | — | — | 5 | 20 | Unlimited | A dash means the feature is not included on that plan. Allowances reset at the start of each calendar month — see [interaction counting](/reference/interaction-counting) for exactly what consumes one. ## Related pages [#related-pages] * [Organization](/organization) * [Interaction counting](/reference/interaction-counting) --- title: "Skills catalogue" url: "/reference/skills-catalog" description: "Every skill you can attach to an agent, grouped by category." productArea: reference audience: ["business-user"] tags: ["skills"] lastReviewed: 2026-08-21 --- # Skills catalogue (/reference/skills-catalog) {/* Generated by scripts/generate-references.ts from snapshots/klicforge-public.json. Do not edit by hand. */} [Skills](/skills-and-tools) are instruction bundles you attach to an agent to shape how it behaves. Attach them from an agent's **Skills** tab. Every plan can attach any skill in the catalogue below. Authoring your own custom skills is the part that is plan-limited — see [plan limits](/reference/plan-limits). ### Agents [#agents] | Skill | ID | | -------------------- | ------------------- | | Agent Builder | `agent-builder` | | Agent Delegation | `agent-delegation` | | Agent Directory | `agent-directory` | | Agent Editing | `agent-editing` | | Evaluations: Builder | `evaluations-admin` | ### Assets [#assets] | Skill | ID | | --------------------- | -------------- | | Assets Storage | `assets` | | Assets Storage: Admin | `assets-admin` | ### Communication [#communication] | Skill | ID | | -------------- | ---------------- | | Email Drafting | `email-drafting` | | FAQ Answering | `faq-answering` | | Gmail | `gmail` | ### Contacts [#contacts] | Skill | ID | | -------------- | ---------------- | | Contacts Admin | `contacts-admin` | | My Contact | `my-contact` | ### Creative [#creative] | Skill | ID | | ------------------ | -------------------- | | Content Generation | `content-generation` | | Image Generation | `image-generation` | ### Data [#data] | Skill | ID | | ------------------------ | ------------------------- | | Data Tables | `tenant-data` | | Data Tables: Admin | `tenant-data-admin` | | Data Tables: Analytics | `tenant-data-analytics` | | Data Tables: Reveal PII | `tenant-data-reveal` | | Data Tables: Scoped Read | `tenant-data-scoped-read` | | Data Tables: My Records | `tenant-data-self` | ### Document Management [#document-management] | Skill | ID | | ------------ | -------------- | | DocuWare | `docuware` | | DocuWare MCP | `docuware-mcp` | ### Education [#education] | Skill | ID | | --------------- | ----------------- | | Explanation | `explanation` | | Quiz Generation | `quiz-generation` | ### Handoff [#handoff] | Skill | ID | | ----------------- | ------------------- | | Escalate to Human | `escalate-to-human` | ### Information [#information] | Skill | ID | | ------------------ | ------------------ | | Research | `research-free` | | Research (Premium) | `research-premium` | | Weather Lookup | `weather-lookup` | | Weather (Premium) | `weather-premium` | ### Knowledge [#knowledge] | Skill | ID | | --------------------- | ---------------------- | | Knowledge Base | `knowledge-base` | | Knowledge Base: Admin | `knowledge-base-admin` | ### Math [#math] | Skill | ID | | ---------- | ------------ | | Calculator | `calculator` | ### Productivity [#productivity] | Skill | ID | | ---------------------------- | --------------------------- | | Calendly | `calendly-scheduling` | | Google Calendar | `google-calendar` | | Google Drive | `google-drive` | | Google Drive (Read Only) | `google-drive-readonly` | | Google Workspace | `google-workspace` | | Google Workspace (Read Only) | `google-workspace-readonly` | | Scheduled Tasks | `scheduling` | | Summarization | `summarization` | ### Safety [#safety] | Skill | ID | | ------------------- | --------------------- | | Child-Safe Learning | `child-safe-learning` | ### Sales [#sales] | Skill | ID | | ---------------------- | ------------------------ | | Order Capture | `order-capture` | | Pricing Calculation | `pricing-calculation` | | Product Recommendation | `product-recommendation` | | Sales Replies | `sales-replies` | ### Skills [#skills] | Skill | ID | | ----------------- | ------------------- | | Skills Management | `skills-management` | ### Support [#support] | Skill | ID | | ------------- | --------------- | | Bug Reporting | `bug-reporting` | ### Tools [#tools] | Skill | ID | | ------------ | ------------------------- | | Custom Tools | `custom-tools-management` | ### Verification [#verification] | Skill | ID | | --------------------- | ----------------------- | | Identity Verification | `identity-verification` | ### Vision [#vision] | Skill | ID | | -------------- | ---------------- | | Image Analysis | `image-analysis` | ### WhatsApp [#whatsapp] | Skill | ID | | ------------------ | -------------------- | | WhatsApp Templates | `whatsapp-templates` | ## Related pages [#related-pages] * [Skills](/skills-and-tools) * [Tools](/skills-and-tools/tools) --- title: "Audience messages" url: "/scheduled-tasks/audience-messages" description: "Message everyone in a data table who matches your filters — one message per row, no AI processing." productArea: scheduled-tasks audience: ["business-user"] tags: ["scheduled-tasks", "data-tables"] lastReviewed: 2026-08-27 --- # Audience messages (/scheduled-tasks/audience-messages) Most scheduled tasks message one contact. An **Audience Message** messages everyone in a [data table](/data-tables) who matches your filters — one message per matching row, on WhatsApp or Telegram. Create one from the agent's **Scheduled Tasks** tab, the same place as any other task, by choosing the **Audience Message** action. ## How it differs from a single-contact task [#how-it-differs-from-a-single-contact-task] | | Agent message | Audience message | | --------------------------- | -------------------------------------------------- | ------------------------------- | | Who receives it | One contact | Every row matching your filters | | The agent runs | Yes — it writes the reply | No — you write the message | | Recipients must be contacts | Yes | No, a table row is enough | | Billing | One [interaction](/reference/interaction-counting) | One interaction per recipient | Because no model runs, an audience message says exactly what you wrote. It is a way to reach a list, not a way to hold a conversation — though if a recipient replies, the agent picks up the conversation the message opened, with the campaign for context, rather than starting cold. There is no "payment reminder" or "birthday" feature. Those are a filter and a template, and building them is the point. ## Choosing who receives it [#choosing-who-receives-it] Pick a **Data table**, then add **Filters**. Everyone in the table who matches them all will be messaged. Only tables the agent has read permission on are offered — see [permissions](/data-tables#permissions) if the table you want is missing. Filter values can use date tokens, resolved against the task's timezone on the day it runs: | Token | Resolves to | | ----------------- | --------------------------------------------------------- | | `{{today}}` | The run date, as `YYYY-MM-DD` | | `{{today+7d}}` | Seven days after the run date | | `{{today-3d}}` | Three days before the run date | | `{{today:MM-DD}}` | Month and day only — for anniversaries, ignoring the year | | `{{today:YYYY}}` | The year only | So "invoices due in a week" is `due_date` **is** `{{today+7d}}`, and "birthdays today" is `birthday` **is** `{{today:MM-DD}}` against a column holding `MM-DD`. ## Which column can be addressed [#which-column-can-be-addressed] **Send to** picks the column holding each recipient's address. Only two column types can be messaged, and which one depends on the channel. | Channel | Column type that works | | -------- | ---------------------- | | WhatsApp | WhatsApp ID | | Telegram | Telegram ID | A **Phone** column does not work for WhatsApp. The two are different identities even when the number looks the same, and a phone column is reserved for a future SMS channel. A **Telegram handle** cannot be messaged either — it can authorise someone who messages your agent, but the Telegram Bot API cannot start a conversation from an @username. An **Email** column has no channel at all. If your table stores numbers in a phone column, add a WhatsApp ID column and populate it with the digits-only form. See [field types](/reference/data-field-types). Rows that match your filters but have nothing in the **Send to** column are skipped, and counted separately in the preview. ### Addressing through a linked table [#addressing-through-a-linked-table] The address does not have to live on the table you are filtering. If your table has a [relation](/reference/data-field-types) column linking each row to one record in another table — a **Payments** table where every payment links to a **Contacts** record — **Send to** also offers that table's columns, shown as **Contact → WhatsApp ID**. That is what lets you filter payments and message people: the filters run on the payments row, the message goes to the number on the linked contact. You do not have to copy the number onto every payment, so it stays correct when the customer changes it. Two limits: * The relation must link to **one** record, not many. A relation that holds several records names no single recipient, so it is not offered. * **Filters still run on the table you picked.** You cannot filter on a linked table's columns — filter on Payments, address through Contacts. A payment whose relation is empty, or points at a record that has since been deleted, is skipped and counted separately in the preview from rows whose contact simply has no WhatsApp ID. The two have different fixes: link the record, or fill in the number. A table with no usable column — its own or through a link — cannot be an audience, and the editor says so rather than letting you save. ## Writing the message [#writing-the-message] On **WhatsApp** you must select an approved template. Meta only allows a business to start a conversation with one, and there is no guarantee the 24-hour window is open when the task runs. See [templates and quality](/channels/whatsapp#templates-and-quality). On **Telegram** you write the message text directly. Template parameters can be filled three ways: | Parameter type | What it fills in | | -------------------- | --------------------------------------- | | **Static text** | The same value for everyone | | **Column** | A value read off each matching row | | **Recipient number** | The number the message is being sent to | **Column** is what makes the message personal — bind a parameter to `first_name` or `amount_due` and every recipient gets their own. There is no contact name or agent name token here, because an audience has no single contact behind it. Columns on a linked table are offered here too, on the same terms as **Send to** above — so a payment reminder can greet people by the name held on their contact record without copying it onto every payment. In Telegram message text they are written `{{contact.first_name}}`. ## Attaching an image [#attaching-an-image] An audience message can carry one image, sent as a **single message** with your text as its caption — not a photo followed by a separate bubble. Everyone in the audience gets the same image; it cannot vary per row. Only images **shared with all conversations** can be attached. Open the file in [Assets](/knowledge/assets), choose **Share with all conversations**, and give the agent permission to send it. Files belonging to one customer — anything they uploaded in a chat, or an image the agent generated for them — are deliberately not offered: an audience message has no single customer behind it, so there is nothing to check a private file against. On **Telegram** you can attach an image to any message. Keep the text under **1,024 characters** — past that, the remainder arrives as a second message. On **WhatsApp** the image travels in the template's header, so it only works with a template that Meta approved **with an Image header**. Create one in WhatsApp Manager with header type **Image**; the Image field appears once you select it, and is then required. A template's layout is fixed when Meta approves it, so an image cannot be added to a text-only template. A message with an image counts as **two interactions** per recipient instead of one. A 500-person birthday campaign with a photo uses 1,000. See [interaction counting](/reference/interaction-counting). ## Checking who matches [#checking-who-matches] Select **Check who matches** before saving. It reports how many people will be messaged, lists the first few with their addresses partly hidden, and tells you how many matching rows were skipped — separately for rows with no address and rows not linked to a record in the table being messaged. The preview stores nothing and sends nothing. Use it — a mistyped filter is invisible until the messages have gone out. ## Updating the row after sending [#updating-the-row-after-sending] **After sending, update** lists the columns to write back to once the message has gone out. Add as many as you need — the rows stack the same way filters do. This matters more than it looks. A recurring task has to change something about the rows it just messaged, or it matches the same people again on the next run. Each row picks a column and what to write into it. What is on offer depends on the column: | Write | Available on | What it writes | | --------------- | ---------------------------------- | ----------------------------------------------- | | the send time | date, date-and-time, text | The moment the message actually went out | | set to | any column you can type a value in | A fixed value you choose | | move forward by | date | The row's own date, plus *N* months | | add to it | number, currency | The row's own number, plus (or minus) an amount | ### Record that they were reached [#record-that-they-were-reached] Write **the send time** into a column, so a task filtered on "reminder sent **is empty**" stops matching that row. ### Move a date forward to the next cycle [#move-a-date-forward-to-the-next-cycle] **Move forward by *N* months** sets the column to its own current value plus that many months, instead of the send time. This is the recurring-due-date shape: a subscription renewal, an appointment, an insurance premium. Say policies carry a `next_premium_due_date`. One task covers every quarterly policy: | Setting | Value | | --------------------- | ------------------------------------------------ | | Filter | `next_premium_due_date` **is** `{{today+7d}}` | | Filter | `premium_frequency` **is** `Quarterly` | | Filter | `policy_status` **is** `Inforce` | | After sending, update | `next_premium_due_date`, forward by **3** months | Each run messages whoever is due in a week and rolls their date to the next quarter, so the following quarter is picked up with no further setup. Author one task per frequency — monthly forward by 1, semi-annual by 6, annual by 12 — each filtered to its own frequency value. Month-ends clamp rather than overflow: a due date on 31 January moves to 28 February (29 in a leap year), not 2 March. A date that was clamped returns to its original day as soon as the target month is long enough, so a policy due on the 31st stays on the 31st. Only **date** columns can be moved forward. Date-and-time and text columns can still be stamped with the send time. If a row's date column is empty or unreadable, that row is still messaged but that column is not written — writing the send time there would silently re-date the record to today. The rest of the row's write-backs still apply. ### Multi-step follow-ups [#multi-step-follow-ups] Stacking is what makes a follow-up sequence possible: a column records which step someone is on, the filter reads it to decide who gets which message, and the write-back advances it. Say contacts carry a `follow_up_msg` number. Author one task per step: | Setting | Step 1 task | Step 2 task | | --------------------- | --------------------------------- | --------------------------------- | | Filter | `follow_up_msg` **is** `1` | `follow_up_msg` **is** `2` | | WhatsApp template | `follow_up_1` | `follow_up_2` | | After sending, update | `follow_up_msg` set to `2` | `follow_up_msg` set to `3` | | After sending, update | `last_contacted_at` the send time | `last_contacted_at` the send time | After step 1 goes out, those contacts stop matching step 1 and start matching step 2, so the next run picks them up with the next message. Someone at `3` matches neither and drops out of the sequence. **Add to it** does the same job without naming the next number — `follow_up_msg` plus **1** reads whatever the row holds and adds one. A row where the column is empty counts as zero, so it becomes 1. Use whichever reads more clearly; the filter still decides the template either way. ### What applies to every write-back [#what-applies-to-every-write-back] A write-back happens only if the agent has update permission on that column, and only after the message has gone out. If one fails, the message is **not** re-sent — the send is the thing that matters, and a failed write-back is recorded in the logs. Columns are handled independently: a column the agent may not write is skipped while the rest still apply. Moving a date forward happens when the **reminder** is sent, not when the customer acts on it. After a payment reminder goes out, the due date already points at the next cycle — so if you also need to know who has not paid, track that in a separate column rather than reading it off the due date. ## Limits [#limits] * An audience is capped at **5,000 recipients**. Over that, the task sends **nothing** rather than an arbitrary subset — messaging half a list is worse than messaging none of it. * If the audience is larger than your workspace's remaining monthly allowance, it also sends nothing. Check [interaction counting](/reference/interaction-counting) and your plan's allowance before scheduling a large run. An image doubles what each recipient costs, so it halves how large an audience your remaining allowance covers. * Messages go out steadily rather than all at once, because WhatsApp and Telegram both pace what a business can send. A large audience takes a while to work through. * Failed sends are retried a few times with an increasing gap. Someone who has blocked your bot, or whose number is not reachable, is not retried. ## Who can be messaged [#who-can-be-messaged] The channel's allow and deny lists apply to every message an audience sends, exactly as they do to someone messaging in. If a channel is **Restricted**, only people its allow list covers are messaged. See [access control](/channels#access-control). On WhatsApp, a customer who has opted out of marketing is skipped for marketing templates, but still receives utility ones. See [opting out of marketing messages](/channels/whatsapp#opting-out-of-marketing-messages). An agent cannot create an audience message for itself. They are made in the dashboard only. ## Troubleshooting [#troubleshooting] | Symptom | Likely cause | | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | **Audience Message** is not offered | The agent has no active WhatsApp or Telegram channel | | The data table is not in the picker | The agent has no read permission on that table — or on the table it links to | | "This table has no WhatsApp ID column" | The addresses are in a phone column, which WhatsApp cannot use | | A linked table's columns are not listed | The relation links to many records, not one — or the agent cannot read the linked table | | "Filters cannot reach through a relation" | A filter names a linked table's column. Filter on the table you picked; address through the link | | The preview finds nobody | A filter names a renamed column, or a date token resolved to a different day in the task's timezone | | Saved, ran, nothing sent | Every match was skipped — no address in the **Send to** column, no linked record, or the channel's lists exclude them | | Fewer messaged than the preview showed | Recipients opted out of marketing, or were added to the deny list since | | The same people are messaged every run | The filter has nothing to exclude them — set **After sending, update** | | "Move forward by" is not offered | The chosen column is not a **date** column. Each column offers only what its type supports | | A date column was not moved forward | That row's date was empty or unreadable, so that column was left alone rather than re-dated to today | | One column updated but another did not | That row could not supply a base value, or the agent has no update permission on that column | | The task failed with "invalid payload" | A write-back names a renamed, encrypted or linked-table column, or a value the column will not accept | | Nothing sent at all on a large audience | The audience is over 5,000, or over your remaining monthly allowance | ## Related pages [#related-pages] * [Scheduled tasks](/scheduled-tasks) * [Data tables](/data-tables) * [WhatsApp setup](/channels/whatsapp) * [Telegram setup](/channels/telegram) * [Access control](/channels#access-control) * [Interaction counting](/reference/interaction-counting) --- title: "Scheduled tasks" url: "/scheduled-tasks" description: "Have an agent reach out proactively — one-off reminders and recurring check-ins delivered to a contact's existing channel." productArea: scheduled-tasks audience: ["business-user"] tags: ["scheduled-tasks"] lastReviewed: 2026-08-26 --- # Scheduled tasks (/scheduled-tasks) A scheduled task lets an agent start the conversation rather than only replying. Follow-up reminders, recurring check-ins, a daily summary — delivered to a contact's existing chat channel. Tasks come in two shapes: one aimed at a single contact, and an [audience message](/scheduled-tasks/audience-messages) aimed at everyone in a data table who matches your filters. Manage them from the **Scheduled Tasks** tab on the agent. ## Creating a task [#creating-a-task] | Field | What it sets | | ----------------- | ---------------------------------------- | | **Title** | A name for you, not shown to the contact | | **Schedule type** | One-off or recurring | | **Run at** | Date and time, for a one-off task | | **Recurrence** | The repeat pattern, for a recurring task | | **Timezone** | Schedules are evaluated in this zone | | **Enabled** | Pause a task without deleting it | | **Action** | What the task actually does | | **Contact** | Who receives it | One-off tasks must be scheduled in the future. Recurring tasks have a minimum interval of five minutes. ## What a task can do [#what-a-task-can-do] | Action | What happens | | -------------------- | ------------------------------------------------------------------------------------------------------------------------ | | **Agent message** | Runs the agent with an instruction and delivers its response | | **Notification** | Delivers a fixed message with no model call | | **Audience message** | Messages everyone in a data table who matches your filters — see [audience messages](/scheduled-tasks/audience-messages) | An **agent message** is billed as [one interaction](/reference/interaction-counting), the same as a user turn, because the model runs. A plain notification is not. An **audience message** costs one interaction per recipient. ## Attaching an image [#attaching-an-image] Any task can carry one image, sent as a **single message** with the message text as its caption rather than a separate bubble. On an agent message the caption is whatever the agent writes when it runs. Only images **shared with all conversations** can be attached — open the file in [Assets](/knowledge/assets), choose **Share with all conversations**, and give the agent permission to send it. On WhatsApp the image travels in the template header, so it needs a template Meta approved **with an Image header**; the Image field appears once you select one, and is then required. A message with an image counts as **two interactions** instead of one. The same rules apply to audience messages — see [attaching an image](/scheduled-tasks/audience-messages#attaching-an-image). ## Choosing the channel [#choosing-the-channel] A task is delivered to the contact through a channel they already use. If you do not pick one, KlicForge uses their WhatsApp identity where available, otherwise the first channel it can reach them on. **Delivering to WhatsApp requires an approved message template.** Meta blocks business-initiated messages outside the 24-hour customer service window unless they use one. A WhatsApp task without a template selected will not send. See [WhatsApp setup](/channels/whatsapp). ## Managing tasks [#managing-tasks] Tasks can be paused, resumed and cancelled. Each task keeps a run history so you can see whether it fired and what happened. A task aimed at a contact KlicForge cannot reach is refused when you save or re-enable it, rather than accepted and then failing quietly at run time. If that happens, the contact has never messaged the agent and has no WhatsApp or Telegram identity on file — see [contacts](/contacts). ## Troubleshooting [#troubleshooting] | Symptom | Likely cause | | -------------------------------------- | ----------------------------------------------------------------------- | | Task never ran | It is disabled, or the agent is not `active` | | Cannot save — no reachable channel | The contact has never messaged and has no WhatsApp or Telegram identity | | Task ran but nothing was delivered | The contact's channel identity stopped working after the task was saved | | WhatsApp task silently does not send | No approved template selected | | Recurring task fires at the wrong time | Timezone is set to something other than the contact's | ## Related pages [#related-pages] * [Audience messages](/scheduled-tasks/audience-messages) * [WhatsApp setup](/channels/whatsapp) * [Contacts](/contacts) * [Interaction counting](/reference/interaction-counting) --- title: "Skills" url: "/skills-and-tools" description: "Reusable instruction modules that shape how an agent responds, and how they differ from tools." productArea: skills-and-tools audience: ["business-user"] tags: ["skills"] lastReviewed: 2026-08-25 --- # Skills (/skills-and-tools) A skill is a reusable block of instructions that gets added to an agent's context at runtime. Skills change *how* an agent behaves — how it formats a code answer, how it triages a support request, how it structures research. **Skills are not tools.** A skill adds instructions. A [tool](/skills-and-tools/tools) runs something and returns data. If you want the agent to *do* something, you want a tool. ## Using skills [#using-skills] * **Browse** — select **Developer → Extensions** in the sidebar to see your own skills, or browse and install built-in ones from the [Marketplace](/marketplace). * **Attach** — open an agent's **Skills** tab and toggle on the skills you want. * **Inspect** — select any skill to read the instructions it injects before you attach it. Skills compose additively. Every attached skill's instructions are present at once, so a small, well-chosen set works better than a long list. ## What skills are good for [#what-skills-are-good-for] Good uses: * Domain behaviour: support triage, lead qualification, research structure * Output shape: how to format code, how to structure a summary * Task-specific method: how to approach scheduling, how to draft an email Poor uses: * **General tone and personality.** Put that in the [SOUL prompt file](/agents/core-prompt-files) instead. Tone in a skill is harder to predict because it competes with every other attached skill. ## Custom skills [#custom-skills] Depending on your plan, you can create your own skills in the dashboard as well as attaching ones from the library. The number of skills you can attach per agent is a plan limit — see [plans and usage](/organization). ### Writing one with the assistant [#writing-one-with-the-assistant] Instead of drafting the instructions yourself, describe the behaviour you want to the [in-dashboard assistant](/troubleshooting/support#in-dashboard-assistant) — "create a skill for handling refund requests", "tighten the wording in the escalation skill". It creates new skills directly. **Changes to an existing skill are proposed, never applied silently**: you get a change set card in the chat listing what would change, exactly like [editing an agent](/agents#editing-with-the-assistant), and nothing is written until you approve it. Built-in library skills are read-only and cannot be edited or deleted. ## Choosing well [#choosing-well] * **Be specific.** Vague instructions produce inconsistent behaviour. * **Watch for conflicts.** Two skills can give contradictory instructions; test combinations in the agent's **Sandbox** tab. * **Fewer is better.** Every attached skill takes up context the agent could be using for your knowledge content. ## Related pages [#related-pages] * [Tools](/skills-and-tools/tools) * [Marketplace](/marketplace) * [Core prompt files](/agents/core-prompt-files) * [Agents overview](/agents) --- title: "Tools" url: "/skills-and-tools/tools" description: "Functions an agent can call to look things up and take actions, including custom webhook tools you define without code." productArea: skills-and-tools audience: ["business-user", "developer"] tags: ["tools"] lastReviewed: 2026-08-25 --- # Tools (/skills-and-tools/tools) A tool is a function the agent can call during a conversation to fetch data or take an action. Unlike a [skill](/skills-and-tools), which only adds instructions, a tool actually runs and returns a result the agent then uses in its answer. ## Using tools [#using-tools] * **Browse** — select **Developer → Extensions** in the sidebar to see your own custom tools, or browse and install built-in ones from the [Marketplace](/marketplace). * **Attach** — open an agent's **Tools** tab and enable the ones it may call. * **Test** — use the **Test** button on a tool's detail view before attaching it. An agent can only call tools you have explicitly enabled for it. This is enforced by the runtime, not just by instructions. ## Built-in tools [#built-in-tools] KlicForge ships a large catalog of built-in tools, grouped by area. Broadly they cover: | Area | What the tools do | | ----------- | ----------------------------------------------------------------------------------- | | Data tables | Read, create, update, search and import records in your [data tables](/data-tables) | | Knowledge | Search and manage [knowledge sources](/knowledge) | | Contacts | Look up and update [contact](/contacts) records | | Email | Search, read, draft and send mail through a connected Gmail account | | WhatsApp | Send templates and manage WhatsApp messaging | | Scheduling | Create and manage [scheduled tasks](/scheduled-tasks) | | Assets | Store, retrieve and send files and images | | Handoff | [Escalate a conversation to a human](/channels) | | Date & time | Resolve dates such as "the second Tuesday of next month" or "in 10 business days" | | Utilities | Calculation, web search, weather, image generation | Built-in tools are read-only in the dashboard. Which ones are available depends on your plan and on which integrations you have connected. ## Custom webhook tools [#custom-webhook-tools] You can turn any external HTTP API into an agent tool without writing code. 1. Select **Extensions → New Tool**. 2. Fill in the tool ID, name, description, HTTP method and endpoint URL. 3. Define path parameters, query parameters, body fields and auth headers. 4. Select **Test Tool** to send a live request and confirm it works. 5. Save. The tool is immediately available to attach to any agent. You can also paste a `curl` command and let the importer populate the form. The **description** is what the agent reads to decide when to call the tool. Write it as instructions to the agent — "Look up an order by its order number" — not as an API summary. A vague description is the most common cause of a tool being called at the wrong moment. ### Supported methods and input mapping [#supported-methods-and-input-mapping] `GET`, `POST`, `PUT`, `PATCH`, `DELETE`. | Input type | How it maps | | ---------------- | ------------------------------------------------ | | Path parameters | Substituted into the URL template: `{paramName}` | | Query parameters | Appended to the URL as `?key=value` | | JSON body | Sent as an `application/json` request body | | Auth headers | Sent as HTTP headers, stored encrypted | ## How a tool call works [#how-a-tool-call-works] 1. The agent decides to call a tool and supplies arguments. 2. KlicForge checks the tool is enabled for that agent. 3. Arguments are validated against the tool's input schema. 4. The tool runs. 5. Output is sanitised before it re-enters the agent's context. 6. The agent continues its answer with the result available. Tool calls do not consume extra allowance — a turn is [one interaction](/reference/interaction-counting) no matter how many tools it calls. ## Security [#security] * Auth headers and credentials are stored encrypted and never returned in any API response. * An agent can only call tools on its own enabled list. * Tool output is treated as data — instruction-like patterns are stripped before it reaches the model, so a compromised endpoint cannot issue commands to your agent. ## Related pages [#related-pages] * [Skills](/skills-and-tools) * [Marketplace](/marketplace) * [Data tables](/data-tables) * [Guardrails](/guardrails) --- title: "Frequently asked questions" url: "/troubleshooting/faq" description: "Answers to common questions about matching a chatter to their own data, and how attachments count toward usage." productArea: troubleshooting audience: ["business-user", "admin", "developer"] tags: ["faq"] lastReviewed: 2026-08-01 --- # Frequently asked questions (/troubleshooting/faq) ## How do I match the person I'm chatting with to a row in my own data table? [#how-do-i-match-the-person-im-chatting-with-to-a-row-in-my-own-data-table] A common pattern: an agent backed by a [data table](/data-tables) needs to answer "what's my order status" or "what's my account balance" — which requires finding the current chatter's own row before it can answer. ### The source of truth: a contact ID field [#the-source-of-truth-a-contact-id-field] Add a field of type **contact ID** to your collection. This is the single source of truth for who a record belongs to: * **It's stamped automatically.** Every time your agent creates a record, the platform fills this field with the current conversation's contact, resolved server-side from the channel the message arrived on. The agent — and therefore anyone chatting with it — can never set or spoof it. * **It's immutable.** Once a record is created, its owning contact cannot be changed. * **It scopes reads.** Set the agent's data table access to self-scoped, on the agent's data table permissions. The agent can then only read rows whose contact ID matches the current contact, so "what's my order status" just works, and one person can never see another person's rows. This is enforced on the server; the agent cannot opt out of the filter. That's the whole pattern: add the contact ID field, turn on self-scoped access, and both writing the owner and filtering to the owner happen automatically. ### Why not just ask for a name, email, or ID number? [#why-not-just-ask-for-a-name-email-or-id-number] Do not have the agent ask the chatting user for their name, email, phone number, or an ID number and then search your data table with that as the lookup key. Anything typed into a chat is a self-reported claim, not proof of identity — anybody can claim to be anybody. An agent that trusts a user-supplied identifier to look up records can be tricked into handing one person's data to someone else. Always identify the caller by the platform-resolved contact ID, never by a value the user asserted in the conversation. Encrypted fields also support exact-match search only and are never returned to the agent in plaintext, so they cannot be used as an identity lookup key either — use the contact ID. ### Don't use an admin skill for this [#dont-use-an-admin-skill-for-this] A contacts-admin style skill is a different tool, meant for workspace admins or internal agents to manage the entire contact list — search across every contact, create, update, merge, delete, and link identities. It is not scoped to "the current caller." Attaching it to a public-facing agent lets that agent, and therefore anyone who can steer it in chat, search and read every contact in your workspace. Reserve admin-level skills for internal agents your own team controls — never attach one to a customer-facing agent. ## Do photo, file, and voice note attachments count as extra interactions? [#do-photo-file-and-voice-note-attachments-count-as-extra-interactions] Yes, per attachment. A turn is billed as one base interaction, plus one more interaction for each photo, file, or voice note attached to that turn — not a flat addition regardless of count. Uploading 5 photos in a single turn adds 5 interactions, 6 total for that turn. This matches the actual processing cost: each attachment gets its own analysis — a vision model per photo, a dedicated pass per file, transcription per voice note. See [interaction counting](/reference/interaction-counting) for the full breakdown. ## Related pages [#related-pages] * [Data tables](/data-tables) * [Interaction counting](/reference/interaction-counting) --- title: "Troubleshooting" url: "/troubleshooting" description: "Common problems by symptom, with the usual cause and where to fix it." productArea: troubleshooting audience: ["business-user", "developer", "admin"] tags: ["troubleshooting"] lastReviewed: 2026-08-14 --- # Troubleshooting (/troubleshooting) Find your symptom below. If it is not here, ask the assistant inside the dashboard — it can see your configuration. ## The agent gives poor answers [#the-agent-gives-poor-answers] | Symptom | Usual cause | Fix | | -------------------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------- | | Answers are vague or generic | No knowledge source attached | Attach one on the agent's Knowledge tab — see [knowledge](/knowledge) | | Says it does not know something that is in your document | Source still processing, or not attached | Check the source status is **completed** | | Ignores knowledge entirely | Answer mode is `tools_only` | See [answer modes](/guardrails/answer-modes) | | Refuses questions it should answer | `grounded_only` and the content is missing | Add the content to knowledge rather than loosening the mode | | Answers confidently but wrongly | Answer mode is too loose | Move to `grounded_only` and enable response validation | | Tone is inconsistent | Tone set in a skill instead of SOUL | Move it to the [SOUL file](/agents/core-prompt-files) | | Behaviour changed unexpectedly | Someone edited the agent | Check [version history](/agents/versioning) | ## Nobody can reach the agent [#nobody-can-reach-the-agent] | Symptom | Usual cause | | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | No response on any channel | Agent status is `draft` or `inactive` | | Widget does not appear | The site's domain is not in allowed origins — see [the web widget](/channels/web-widget) | | `window.AgentKit is undefined` | Script tag loads after your init code — see [the widget SDK](/build/widget-sdk) | | Some people get no reply | A deny list entry is filtering them — see [access control](/channels#access-control) | | Nobody gets a reply on one channel | The channel is **Restricted** and its allow list matches nobody | | A widget visitor is refused | Data table entries do not authorise widget visitors — see [the web widget](/channels/web-widget#restricting-who-can-chat) | | Telegram bot silent | Token mistyped, or the webhook needs re-registering — see [Telegram](/channels/telegram) | | WhatsApp worked then stopped | A temporary access token expired — see [WhatsApp](/channels/whatsapp) | | Agent cannot message a WhatsApp user first | Expected — needs an approved template and an open 24-hour window | ## Tools and data [#tools-and-data] | Symptom | Usual cause | | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | Agent never calls a tool | Tool not enabled on the agent, or its description is too vague | | Agent calls a tool at the wrong moment | Description describes the API rather than when to use it — see [tools](/skills-and-tools/tools) | | Agent cannot see a data table | No permission granted on the table's Permissions tab | | Agent sees no rows | A row scope rule found no matching identity — scope rules fail closed | | Cannot search a field by partial match | The field is encrypted — it matches on a whole value, or a whole word if set to Match any word. Never on a fragment | | Agent will not read back a value it saved | The field is read-blocked, which is the safe default for personal data | | Agent says it will do something, nothing happens | It described the action instead of performing it. It retries once and then reports the failure — if it persists, check the tool is enabled on the agent | | Agent cannot save a value to a choice field | The field has no options configured — add them on the table's Fields tab | ## Uploads and files [#uploads-and-files] | Symptom | Usual cause | | -------------------------------- | ---------------------------------------------------- | | Upload rejected | Unsupported type, over 30 MB, or no extractable text | | Scanned PDF produces nothing | Reprocess the source and force vision extraction | | Only part of a long PDF was read | Vision extraction caps at the first 50 pages | ## Usage and billing [#usage-and-billing] | Symptom | Usual cause | | -------------------------------------- | ------------------------------------------------------------------------------------------------------ | | Allowance used faster than expected | Attachments each count as an interaction — see [interaction counting](/reference/interaction-counting) | | Evaluation run cost more than expected | Judged cases add one interaction per case | | A feature is greyed out | It requires a higher plan — see [workspace](/organization) | | Cannot publish an agent version | Your plan is below the versioning tier, or a publish gate is blocking | ## Memory [#memory] | Symptom | Usual cause | | ----------------------------------------------- | ------------------------------------------------------- | | Memory toggle is locked | No business domain selected on the agent | | Agent does not remember an earlier conversation | Extraction runs after a conversation ends, not during | | Agent remembers something it should not | Edit or remove it under Contacts → the contact → Memory | ## Still stuck [#still-stuck] Ask the in-dashboard assistant, which can see your actual configuration, or see [getting help](/troubleshooting/support) for how to reach the team. ## Related pages [#related-pages] * [Guardrails](/guardrails) * [Channels](/channels) * [Glossary](/reference/glossary) * [FAQ](/troubleshooting/faq) * [Getting help](/troubleshooting/support) --- title: "Getting help" url: "/troubleshooting/support" description: "Where to report bugs, ask questions, and submit privacy requests." productArea: troubleshooting audience: ["business-user", "admin", "developer"] tags: ["support"] lastReviewed: 2026-08-22 --- # Getting help (/troubleshooting/support) ## Report a bug or issue [#report-a-bug-or-issue] The primary channel for bug reports, unexpected behaviour, and product issues is the KlicForge Issue Tracker bot on Telegram: **@KlicIssueTrackerBot**. Use it for bugs or errors in the dashboard, unexpected agent behaviour, feature requests, or anything you want tracked and responded to by the team. Include a short description of what happened, steps to reproduce if applicable, and any error messages or screenshots. ## Email [#email] **[hello@klicforge.ai](mailto:hello@klicforge.ai)** — enterprise and billing inquiries, account access issues, sales and partnership discussions. ## In-dashboard assistant [#in-dashboard-assistant] Open **Chats** in the dashboard sidebar and start a conversation with Klic, the in-dashboard assistant, to ask about agent configuration, skills, tools, knowledge sources, models, notifications, channels, memory, and scheduled tasks. Expand **Chats** for earlier conversations, or use **New chat** to start a fresh one. It can also make changes for you: ask it to adjust an agent and it proposes a **change set** — a card showing exactly what would change, which you approve or discard. Nothing is applied without your approval. See [editing with the assistant](/agents#editing-with-the-assistant). For owners and admins, it can also explain why an agent answered badly in a past conversation and turn that into a regression test — see [ask the assistant to diagnose it](/conversations#ask-the-assistant-to-diagnose-it). ## Privacy requests [#privacy-requests] To submit a data access, deletion, or other privacy request, email **[privacy@klicforge.ai](mailto:privacy@klicforge.ai)** or use the opt-out page at [klicforge.ai/privacy/opt-out](https://klicforge.ai/privacy/opt-out). Standard response time is 30 days, up to 45 days for complex requests. See [security and privacy](/organization/security-and-privacy) for more. ## Related pages [#related-pages] * [Troubleshooting](/troubleshooting) * [Security and privacy](/organization/security-and-privacy)