<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://docs.qefro.com/blog</id>
    <title>Qefro Blog</title>
    <updated>2026-07-27T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://docs.qefro.com/blog"/>
    <subtitle>Product, engineering, and architecture updates from the Qefro team.</subtitle>
    <icon>https://docs.qefro.com/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[Integrating Your Business System with Qefro: REST API vs SDK]]></title>
        <id>https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk</id>
        <link href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk"/>
        <updated>2026-07-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Learn how to integrate your CRM, ERP, Helpdesk, ecommerce platform, or custom application with Qefro using either the REST API or the official JavaScript and Rust SDKs.]]></summary>
        <content type="html"><![CDATA[<p>Your business already runs on a CRM, an ERP, a helpdesk, or a homegrown platform. Qefro is designed to plug into that stack — not replace it. This guide compares the two supported integration paths for <strong>Business Tools</strong> — <strong>REST / OpenAPI</strong> and the official <strong>JavaScript and Rust Backend SDKs</strong> — with working code for both so you can pick the right one for your team.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-integrate-with-qefro">Why Integrate with Qefro?<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#why-integrate-with-qefro" class="hash-link" aria-label="Direct link to Why Integrate with Qefro?" title="Direct link to Why Integrate with Qefro?" translate="no">​</a></h2>
<p>Most companies that adopt AI-powered customer support already have systems that hold the answers customers need:</p>
<ul>
<li class=""><strong>CRM</strong> — customer records, account history, ownership</li>
<li class=""><strong>ERP</strong> — orders, inventory, invoicing</li>
<li class=""><strong>Helpdesk</strong> — tickets, macros, resolution history</li>
<li class=""><strong>Internal dashboards</strong> — operational and support tooling</li>
<li class=""><strong>Ecommerce platforms</strong> — carts, orders, returns</li>
<li class=""><strong>Customer portals</strong> — self-service account management</li>
<li class=""><strong>Mobile apps</strong> — in-app support surfaces</li>
<li class=""><strong>Desktop applications</strong> — point-of-sale and back-office software</li>
</ul>
<p>Replacing any of these to add AI would be expensive and risky. Instead, Qefro integrates <em>with</em> them. The <a class="" href="https://docs.qefro.com/docs/platform/knowledge-platform">Knowledge Base</a> answers policy and FAQ questions from your documents, and <a class="" href="https://docs.qefro.com/docs/business-tools">Business Tools</a> let the assistant <strong>execute real actions</strong> in your systems — "Where is order ORD-1002?", "Create a ticket", "Cancel my subscription" — with live data from your APIs.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>The AI never calls your APIs directly. Every action flows through the shared <a class="" href="https://docs.qefro.com/docs/business-tools/runtime">Business Tool Runtime</a>, which validates parameters, applies encrypted credentials, and logs every invocation — whether the tool is REST or SDK.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="two-integration-approaches">Two Integration Approaches<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#two-integration-approaches" class="hash-link" aria-label="Direct link to Two Integration Approaches" title="Direct link to Two Integration Approaches" translate="no">​</a></h2>
<p>There are two supported ways to connect your backend, and both register Business Tools in the same workspace and execute through the same runtime. The difference is <strong>how Qefro reaches your backend</strong>:</p>
<ol>
<li class=""><strong>REST / OpenAPI</strong> — Qefro acts as the HTTP client and calls your existing HTTPS API directly. Configure a tool manually or bulk-import an OpenAPI 3.x spec.</li>
<li class=""><strong>Backend SDK</strong> — the official <strong>JavaScript</strong> (<code>@qefro-ai/backend</code>) or <strong>Rust</strong> (<code>qefro-backend-sdk</code>) framework runs <em>in your backend</em> and exposes one signed webhook (<code>POST /qefro</code>) that Qefro calls.</li>
</ol>
<p>As a rule of thumb: use <strong>REST</strong> when you already have HTTPS endpoints and operations are CRUD-like. Use the <strong>SDK</strong> when customer authentication (OTP, login), multi-step workflows, or organization logic belongs in your code.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="option-1-rest-api">Option 1: REST API<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#option-1-rest-api" class="hash-link" aria-label="Direct link to Option 1: REST API" title="Direct link to Option 1: REST API" translate="no">​</a></h2>
<p>With a REST Business Tool, Qefro calls your API — it substitutes URL parameters, applies the encrypted credential, validates schemas against your <code>input_schema</code>, and logs every call. If your platform exposes an HTTPS endpoint, it can become a Business Tool.</p>
<p>Benefits:</p>
<ul>
<li class=""><strong>Works with any language</strong> — your API can be Python, Java, C#, Go, PHP, anything that serves HTTPS</li>
<li class=""><strong>OpenAPI compatible</strong> — import an OpenAPI 3.x spec to bulk-create tools from existing operations</li>
<li class=""><strong>Easy to debug</strong> — dry-run tools from the Admin Console or with <code>curl</code>, inspect execution logs per call</li>
<li class=""><strong>Suitable for microservices</strong> — each service exposes its own endpoints; each becomes its own tool</li>
<li class=""><strong>Ideal for existing systems</strong> — no new dependency, no redeploy; point Qefro at what you already run</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="defining-a-rest-tool">Defining a REST tool<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#defining-a-rest-tool" class="hash-link" aria-label="Direct link to Defining a REST tool" title="Direct link to Defining a REST tool" translate="no">​</a></h3>
<p>A manual REST tool is method + URL template + JSON Schema. Path placeholders like <code>{order_id}</code> map to <code>input_schema</code> properties that the LLM fills from conversation:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">GET https://api.example.com/orders/{order_id}</span><br></div></code></pre></div></div>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"type"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"object"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"properties"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"order_id"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"type"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"string"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"description"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Order ID such as ORD-1001"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"required"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"order_id"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Remaining parameters become the query string on <code>GET</code> or the JSON body on <code>POST</code>/<code>PUT</code>/<code>PATCH</code>. Invalid LLM parameters are rejected by input validation <em>before</em> they ever reach your API.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="testing-with-curl">Testing with curl<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#testing-with-curl" class="hash-link" aria-label="Direct link to Testing with curl" title="Direct link to Testing with curl" translate="no">​</a></h3>
<p>You can dry-run any tool with sample arguments through the Admin API:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-sS</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-H</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Authorization: Bearer </span><span class="token string variable" style="color:#36acaa">$ADMIN_JWT</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-H</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  https://api.qefro.com/api/v1/tools/</span><span class="token variable" style="color:#36acaa">$TOOL_ID</span><span class="token plain">/test </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'{"arguments": {"order_id": "ORD-1001"}}'</span><br></div></code></pre></div></div>
<p>And review what actually happened in production:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-sS</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-H</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Authorization: Bearer </span><span class="token string variable" style="color:#36acaa">$ADMIN_JWT</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  https://api.qefro.com/api/v1/tools/</span><span class="token variable" style="color:#36acaa">$TOOL_ID</span><span class="token plain">/logs</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="authentication">Authentication<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#authentication" class="hash-link" aria-label="Direct link to Authentication" title="Direct link to Authentication" translate="no">​</a></h3>
<p>Each REST tool has one auth mode. Qefro stores the credential encrypted and applies it only at execution time:</p>
<table><thead><tr><th>Mode</th><th>Outbound behavior</th><th>Use when</th></tr></thead><tbody><tr><td><code>NONE</code></td><td>No credential header</td><td>Public read APIs</td></tr><tr><td><code>API_KEY</code></td><td><code>X-API-Key: &lt;secret&gt;</code></td><td>Vendor / internal service keys</td></tr><tr><td><code>BEARER_TOKEN</code></td><td><code>Authorization: Bearer &lt;secret&gt;</code></td><td>Service-account bearer tokens</td></tr><tr><td><code>END_USER_IDENTITY</code></td><td>Forwards the signed-in customer's JWT</td><td>Customer-scoped APIs on the Widget</td></tr></tbody></table>
<p><code>END_USER_IDENTITY</code> is the key one for customer-facing actions: when your app calls <code>widget.identify()</code> with a user JWT, Qefro forwards it as <code>Authorization: Bearer</code> on the outbound call, and <strong>your API validates it</strong> — Qefro never becomes your identity provider. See <a class="" href="https://docs.qefro.com/docs/business-tools/identity-forwarding">Identity forwarding</a>.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>Only HTTPS URLs are accepted, and the runtime rejects private IPs and cloud metadata hosts (SSRF protection). Secrets live encrypted in Qefro — never in widget JavaScript or in OpenAPI specs you upload.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="option-2-official-sdk">Option 2: Official SDK<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#option-2-official-sdk" class="hash-link" aria-label="Direct link to Option 2: Official SDK" title="Direct link to Option 2: Official SDK" translate="no">​</a></h2>
<p>The Backend SDK inverts the model: instead of configuring HTTP calls in the console, you register <strong>tool handlers in code</strong>, running in your own backend. Qefro discovers them over one signed webhook using four protocol messages — <code>ping</code>, <code>tools.list</code>, <code>tool.invoke</code>, and <code>tool.resume</code>. Qefro currently provides two official SDKs:</p>
<ul>
<li class=""><strong>JavaScript SDK</strong> — <a href="https://www.npmjs.com/package/@qefro-ai/backend" target="_blank" rel="noopener noreferrer" class=""><code>@qefro-ai/backend</code></a> for Node.js and TypeScript</li>
<li class=""><strong>Rust SDK</strong> — <a href="https://docs.rs/qefro-backend-sdk" target="_blank" rel="noopener noreferrer" class=""><code>qefro-backend-sdk</code></a> for async Rust on Tokio</li>
</ul>
<p>Both target feature parity, so choosing one is a question of your stack, not of capability. The SDK shines where REST gets awkward: customer lookup and authorization (OTP inside chat, via challenge/resume), multi-step workflows, and business rules that span several internal services.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="javascript-example">JavaScript Example<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#javascript-example" class="hash-link" aria-label="Direct link to JavaScript Example" title="Direct link to JavaScript Example" translate="no">​</a></h2>
<p>Install the SDK and set the signing secret shared with the Admin Console:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> @qefro-ai/backend</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">QEFRO_SIGNING_SECRET</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"your-signing-secret"</span><br></div></code></pre></div></div>
<p>Then create the app, register a tool handler, and listen on the webhook path:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> Qefro </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@qefro-ai/backend'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Verify incoming webhook signatures with the shared secret</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> app </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Qefro</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  signingSecret</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">env</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">QEFRO_SIGNING_SECRET</span><span class="token operator" style="color:#393A34">!</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Register a Business Tool handler — discovered via Sync Tools</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">tool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'order_status_check'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    description</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Look up order by ID when customer provides order_id.'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    auth</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'none'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    input_schema</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      type</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'object'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      properties</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> order_id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> type</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'string'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      required</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'order_id'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ctx</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> orderId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ctx</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">parameters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">order_id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toUpperCase</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> orderService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">orderId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// One signed webhook handles ping, tools.list, tool.invoke, tool.resume</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listen</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> port</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8088</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> path</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'/qefro'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Deploy, then in the Admin Console create an <strong>SDK Connection</strong> (webhook URL + signing secret), hit <strong>Test Connection</strong>, and run <strong>Sync Tools</strong> to register the handlers into your workspace. Full walkthrough: <a class="" href="https://docs.qefro.com/docs/guides/register-sdk-business-tools">Register SDK Business Tools</a>.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>When a customer must prove who they are <em>inside the chat</em>, add a Customer Provider with <code>app.customer({ lookup, authorize })</code>. Your <code>authorize()</code> can return a <code>challenge</code> (e.g. email OTP), and Qefro relays the code and resumes the tool via <code>tool.resume</code> — no login page required. See <a class="" href="https://docs.qefro.com/docs/business-tools/challenge-resume">Challenge / Resume</a>.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rust-example">Rust Example<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#rust-example" class="hash-link" aria-label="Direct link to Rust Example" title="Direct link to Rust Example" translate="no">​</a></h2>
<p>Add the dependencies:</p>
<div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-toml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">[</span><span class="token table class-name">dependencies</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key property" style="color:#36acaa">qefro-backend-sdk</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"1"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key property" style="color:#36acaa">tokio</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token key property" style="color:#36acaa">version</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"1"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token key property" style="color:#36acaa">features</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"macros"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rt-multi-thread"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"signal"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>The same handler, fully async on Tokio:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">qefro_backend_sdk</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">ListenOptions</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Qefro</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">QefroConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ToolAuthMode</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ToolMetadata</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">serde_json</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token plain">json</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[tokio::main]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">anyhow</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Verify incoming webhook signatures with the shared secret</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> app </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Qefro</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">QefroConfig</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">env</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"QEFRO_SIGNING_SECRET"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Register a Business Tool handler — discovered via Sync Tools</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">tool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ToolMetadata</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"order_status_check"</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">into</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            description</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Some</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Look up order by ID when customer provides order_id."</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">into</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            auth</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ToolAuthMode</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            input_schema</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Some</span><span class="token punctuation" style="color:#393A34">(</span><span class="token macro property" style="color:#36acaa">json!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"type"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"object"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"properties"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"order_id"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"type"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"string"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"required"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"order_id"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">..</span><span class="token class-name">Default</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">ctx</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">move</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token macro property" style="color:#36acaa">json!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"order_id"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ctx</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">parameters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"order_id"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"status"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shipped"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// One signed webhook handles ping, tools.list, tool.invoke, tool.resume</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> handle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listen</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ListenOptions</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8088</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"listening on {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token namespace" style="opacity:0.7">tokio</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">signal</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">ctrl_c</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Every incoming request is HMAC-SHA256 signed (<code>X-Qefro-Signature</code>, <code>X-Qefro-Timestamp</code>); the framework verifies signatures and routes protocol messages so you only write handlers.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-teams-prefer-the-sdks">Why teams prefer the SDKs<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#why-teams-prefer-the-sdks" class="hash-link" aria-label="Direct link to Why teams prefer the SDKs" title="Direct link to Why teams prefer the SDKs" translate="no">​</a></h3>
<ul>
<li class=""><strong>Type safety</strong> — tool definitions and handler contexts are checked at compile time</li>
<li class=""><strong>Built-in authentication</strong> — signature verification and challenge/resume orchestration are handled for you</li>
<li class=""><strong>Better developer experience</strong> — handlers live next to your domain code, with autocomplete and typed errors</li>
<li class=""><strong>Cleaner code</strong> — no webhook plumbing; <code>app.listen()</code> covers the whole protocol</li>
<li class=""><strong>Easier upgrades</strong> — add or rename a handler, redeploy, re-run Sync Tools</li>
<li class=""><strong>Automatic serialization</strong> — return structured JSON; the runtime maps it into chat safely</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rest-api-or-sdk">REST API or SDK?<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#rest-api-or-sdk" class="hash-link" aria-label="Direct link to REST API or SDK?" title="Direct link to REST API or SDK?" translate="no">​</a></h2>
<table><thead><tr><th>Feature</th><th>REST API</th><th>JavaScript SDK</th><th>Rust SDK</th></tr></thead><tbody><tr><td>Learning curve</td><td>Low — configure existing endpoints</td><td>Low — familiar npm workflow</td><td>Moderate — requires async Rust</td></tr><tr><td>Boilerplate</td><td>None in your code (config in console)</td><td>Minimal — handlers only</td><td>Minimal — handlers only</td></tr><tr><td>Type safety</td><td>Your API's — Qefro validates JSON Schema</td><td>Full TypeScript types</td><td>Full compile-time types</td></tr><tr><td>Language support</td><td>Any language that serves HTTPS</td><td>Node.js / TypeScript</td><td>Rust</td></tr><tr><td>Performance</td><td>One HTTP hop</td><td>Webhook + your handler logic</td><td>Webhook + zero-cost async handlers</td></tr><tr><td>Ease of use</td><td>High for CRUD; awkward for multi-step</td><td>High, incl. OTP / challenge flows</td><td>High, incl. OTP / challenge flows</td></tr><tr><td>Best use case</td><td>Existing APIs, vendor SaaS, OpenAPI specs</td><td>Node/Next.js/Express backends with auth flows</td><td>Axum / Actix / Tokio services with auth flows</td></tr></tbody></table>
<p>Real products mix both: core domain logic in SDK handlers, vendor APIs (Stripe, Shippo) as REST tools. See <a class="" href="https://docs.qefro.com/docs/business-tools/mixed-integrations">Mixed integrations</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example-architecture">Example Architecture<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#example-architecture" class="hash-link" aria-label="Direct link to Example Architecture" title="Direct link to Example Architecture" translate="no">​</a></h2>
<p>Whichever path you choose, the flow through the platform is the same:</p>
<!-- -->
<p>The workspace enforces tenancy, the knowledge base supplies grounded facts, the tool runtime executes actions against your systems — and the response flows back to whatever channel your customer is already using.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="best-practices">Best Practices<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#best-practices" class="hash-link" aria-label="Direct link to Best Practices" title="Direct link to Best Practices" translate="no">​</a></h2>
<p>A few rules that hold regardless of the integration path:</p>
<ul>
<li class=""><strong>Store API keys securely</strong> — REST tool secrets and SDK signing secrets are encrypted at rest in Qefro; on your side, use environment variables or a secret manager, never source control.</li>
<li class=""><strong>Never expose secrets in frontend code</strong> — widget JavaScript is public; credentials belong in tool config or your backend only.</li>
<li class=""><strong>Use HTTPS</strong> — the runtime rejects plain-HTTP tool URLs outright.</li>
<li class=""><strong>Handle API errors gracefully</strong> — return clear error shapes; the runtime maps them to user-safe text, and the REST executor retries transient failures with bounded backoff (design writes to be idempotent).</li>
<li class=""><strong>Rotate credentials regularly</strong> — rotate REST secrets via the Admin Console and SDK signing secrets per connection; each connection has an Enabled kill switch.</li>
<li class=""><strong>Prefer SDKs for new projects</strong> — typed handlers and native OTP/challenge flows beat hand-rolled auth endpoints.</li>
<li class=""><strong>Use REST for unsupported languages</strong> — any HTTPS API can be a tool, no SDK required.</li>
</ul>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>Importing an OpenAPI spec is like granting broad API access: always preview the operations and deselect <code>DELETE</code>, bulk-export, and admin paths before applying. See <a class="" href="https://docs.qefro.com/docs/guides/import-openapi">Import OpenAPI</a>.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="which-should-you-choose">Which Should You Choose?<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#which-should-you-choose" class="hash-link" aria-label="Direct link to Which Should You Choose?" title="Direct link to Which Should You Choose?" translate="no">​</a></h2>
<p><strong>Use the REST API when:</strong></p>
<ul>
<li class="">Your backend is in a language without an official SDK (Python, Java, Go, C#, PHP, …)</li>
<li class="">You're building microservices and each already exposes clean CRUD endpoints</li>
<li class="">You're connecting existing enterprise systems or vendor SaaS APIs — especially with an OpenAPI spec to import</li>
</ul>
<p><strong>Use the JavaScript SDK when:</strong></p>
<ul>
<li class="">You're building Node.js services</li>
<li class="">You're integrating Qefro into Next.js applications</li>
<li class="">You're adding tool handlers alongside existing Express APIs</li>
</ul>
<p><strong>Use the Rust SDK when:</strong></p>
<ul>
<li class="">You're building high-performance backends where latency and throughput matter</li>
<li class="">You're using Axum for your API layer</li>
<li class="">You're using Actix for your web services</li>
<li class="">You're already on the Tokio async runtime</li>
</ul>
<p>And whenever customers must log in or verify via OTP <em>inside the chat</em>, prefer the SDK — challenge/resume is native there, while REST would force you to build and orchestrate your own OTP API.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://docs.qefro.com/blog/integrating-business-system-rest-vs-sdk#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>Both integration paths lead to the same place: the same workspace, the same Business Tool runtime, and grounded answers backed by your knowledge base and live systems. <strong>REST</strong> offers universal compatibility — any HTTPS API in any language becomes a tool, with OpenAPI import for bulk onboarding. The <strong>JavaScript and Rust SDKs</strong> provide the best developer experience — typed handlers, signed webhooks, and native customer authentication flows.</p>
<p>There is no wrong choice, only the one that fits your stack. If you already have an API, register it as a REST tool and confirm the flow with the console's Test Tool. If you're writing new Node.js or Rust code — or need OTP in chat — start with the SDK. For the full decision matrix, see <a class="" href="https://docs.qefro.com/docs/business-tools/rest-vs-sdk">REST vs Backend SDK</a>.</p>]]></content>
        <author>
            <name>Qefro Team</name>
            <uri>https://qefro.com</uri>
        </author>
        <category label="Engineering" term="Engineering"/>
        <category label="Tutorials" term="Tutorials"/>
        <category label="Platform" term="Platform"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI Workspace vs AI chatbot — choosing the right unit of design]]></title>
        <id>https://docs.qefro.com/blog/ai-workspace-vs-chatbot</id>
        <link href="https://docs.qefro.com/blog/ai-workspace-vs-chatbot"/>
        <updated>2026-07-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[When a simple chatbot is enough, and when you need AI Workspaces with isolation, Employee AI, Business Actions, and multi-tenant RBAC.]]></summary>
        <content type="html"><![CDATA[<p>An <strong>AI chatbot</strong> is usually a conversational UI over one knowledge dump. An <strong>AI Workspace</strong> is an operating unit — knowledge, instructions, tools, conversations, and channel bindings — built for multi-team, multi-tenant use.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quick-comparison">Quick comparison<a href="https://docs.qefro.com/blog/ai-workspace-vs-chatbot#quick-comparison" class="hash-link" aria-label="Direct link to Quick comparison" title="Direct link to Quick comparison" translate="no">​</a></h2>
<table><thead><tr><th>Need</th><th>Chatbot often enough</th><th>Prefer AI Workspaces</th></tr></thead><tbody><tr><td>One public FAQ site</td><td>Yes</td><td>Optional</td></tr><tr><td>Support + HR + IT isolation</td><td>No</td><td>Yes</td></tr><tr><td>Employee portal with RBAC</td><td>Rare</td><td>Yes</td></tr><tr><td>Authorized API actions</td><td>Varies</td><td>First-class Business Actions</td></tr><tr><td>Widget + WhatsApp + portal</td><td>Rare</td><td>Yes</td></tr></tbody></table>
<p>Concept page: <a class="" href="https://docs.qefro.com/docs/concepts/ai-workspace-vs-ai-chatbot">AI Workspace vs AI Chatbot</a>. Definition: <a class="" href="https://docs.qefro.com/docs/concepts/what-is-an-ai-workspace">What is an AI Workspace?</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="evaluation-questions-that-cut-through-marketing">Evaluation questions that cut through marketing<a href="https://docs.qefro.com/blog/ai-workspace-vs-chatbot#evaluation-questions-that-cut-through-marketing" class="hash-link" aria-label="Direct link to Evaluation questions that cut through marketing" title="Direct link to Evaluation questions that cut through marketing" translate="no">​</a></h2>
<ol>
<li class="">What is the <strong>isolation unit</strong> — bot, project, or workspace?</li>
<li class="">Who can call which <strong>tools</strong>, and are calls logged?</li>
<li class="">Is there an <strong>employee portal</strong> with workspace grants?</li>
<li class="">How does <strong>tenancy</strong> prevent cross-customer retrieval?</li>
</ol>
<p>Vendor matrices (educational, not sales sheets): <a class="" href="https://docs.qefro.com/docs/compare/chatbase-vs-qefro">Compare</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="if-you-are-migrating-from-a-chatbot">If you are migrating from a chatbot<a href="https://docs.qefro.com/blog/ai-workspace-vs-chatbot#if-you-are-migrating-from-a-chatbot" class="hash-link" aria-label="Direct link to If you are migrating from a chatbot" title="Direct link to If you are migrating from a chatbot" translate="no">​</a></h2>
<ol>
<li class="">Map audiences (customer vs employee).</li>
<li class="">Split corpora into workspaces.</li>
<li class="">Re-validate citations before enabling tools.</li>
<li class="">Add channels only after knowledge quality is stable.</li>
</ol>
<p>Guides: <a class="" href="https://docs.qefro.com/docs/getting-started/quick-start">Quick Start</a>, <a class="" href="https://docs.qefro.com/docs/guides/production-deployment">Production Deployment</a>.</p>]]></content>
        <author>
            <name>Qefro Team</name>
            <uri>https://qefro.com</uri>
        </author>
        <category label="Architecture" term="Architecture"/>
        <category label="Product" term="Product"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[How AI Workspaces isolate knowledge and actions]]></title>
        <id>https://docs.qefro.com/blog/ai-workspaces-architecture</id>
        <link href="https://docs.qefro.com/blog/ai-workspaces-architecture"/>
        <updated>2026-07-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Why AI Workspaces are the isolation unit for knowledge, Business Tools, and conversations inside a Qefro organization — and how that differs from a single chatbot index.]]></summary>
        <content type="html"><![CDATA[<p>An <strong>AI Workspace</strong> is the primary isolation unit inside a Qefro organization: knowledge, instructions, Business Tools, and conversations stay scoped to that workspace.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-failure-mode-we-designed-against">The failure mode we designed against<a href="https://docs.qefro.com/blog/ai-workspaces-architecture#the-failure-mode-we-designed-against" class="hash-link" aria-label="Direct link to The failure mode we designed against" title="Direct link to The failure mode we designed against" translate="no">​</a></h2>
<p>When Support FAQs, HR policy, and IT runbooks share one retrieval index, two things happen:</p>
<ol>
<li class=""><strong>Wrong answers</strong> — the model cites the nearest-sounding passage, not the right audience’s policy.</li>
<li class=""><strong>Wrong blast radius</strong> — a public widget can surface internal content, or an internal tool can become callable from a customer channel.</li>
</ol>
<p>Workspaces make isolation the default. Channels (website widget, WhatsApp, Internal Portal) bind to workspaces you choose — they do not invent a shared mega-index.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="layered-model">Layered model<a href="https://docs.qefro.com/blog/ai-workspaces-architecture#layered-model" class="hash-link" aria-label="Direct link to Layered model" title="Direct link to Layered model" translate="no">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Organization (tenant)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  └── AI Workspace (Support | HR | IT | …)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ├── Knowledge (hybrid RAG)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ├── Instructions</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ├── Business Tools → Business Actions</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        └── Conversations</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>Tenant</strong> isolates customers from each other.</li>
<li class=""><strong>Workspace</strong> isolates teams and audiences inside a tenant.</li>
</ul>
<p>See <a class="" href="https://docs.qefro.com/docs/concepts/multi-tenant-ai-architecture">Multi-tenant AI Architecture</a> and <a class="" href="https://docs.qefro.com/docs/concepts/what-is-an-ai-workspace">What is an AI Workspace?</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="customer-vs-employee-binding">Customer vs employee binding<a href="https://docs.qefro.com/blog/ai-workspaces-architecture#customer-vs-employee-binding" class="hash-link" aria-label="Direct link to Customer vs employee binding" title="Direct link to Customer vs employee binding" translate="no">​</a></h2>
<table><thead><tr><th>Audience</th><th>Typical workspace</th><th>Channel</th></tr></thead><tbody><tr><td>External customers</td><td>Customer Support</td><td>Website widget, WhatsApp</td></tr><tr><td>Employees</td><td>HR / IT / Ops</td><td>Internal Portal + RBAC</td></tr></tbody></table>
<p>Do not share one workspace across both audiences unless the corpus is intentionally identical and tools are safe for both. Details: <a class="" href="https://docs.qefro.com/docs/concepts/customer-ai-vs-employee-ai">Customer AI vs Employee AI</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="practical-checklist">Practical checklist<a href="https://docs.qefro.com/blog/ai-workspaces-architecture#practical-checklist" class="hash-link" aria-label="Direct link to Practical checklist" title="Direct link to Practical checklist" translate="no">​</a></h2>
<ol>
<li class="">Create one workspace per audience or team.</li>
<li class="">Ingest only documents that audience is allowed to see.</li>
<li class="">Attach Business Tools last — and only tools that belong in that scope.</li>
<li class="">Bind the widget <code>data-workspace-id</code> (or portal grants) deliberately.</li>
<li class="">Cross-test: ask Support questions against an HR workspace to prove isolation.</li>
</ol>
<p>Platform reference: <a class="" href="https://docs.qefro.com/docs/platform/ai-workspaces">AI Workspaces</a>. Security reference: <a class="" href="https://docs.qefro.com/docs/security/tenant-isolation">Tenant Isolation</a>.</p>]]></content>
        <author>
            <name>Qefro Team</name>
            <uri>https://qefro.com</uri>
        </author>
        <category label="Architecture" term="Architecture"/>
        <category label="AI" term="AI"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Customer AI vs Employee AI — same platform, different boundaries]]></title>
        <id>https://docs.qefro.com/blog/customer-ai-vs-employee-ai</id>
        <link href="https://docs.qefro.com/blog/customer-ai-vs-employee-ai"/>
        <updated>2026-07-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How Qefro runs external Customer AI (widget, WhatsApp) and internal Employee AI (Internal Portal) from one Admin Console without mixing knowledge or tools.]]></summary>
        <content type="html"><![CDATA[<p><strong>Customer AI</strong> and <strong>Employee AI</strong> share Qefro’s workspace technology — but they differ in audience, channels, identity, and what knowledge is safe to expose.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="side-by-side">Side-by-side<a href="https://docs.qefro.com/blog/customer-ai-vs-employee-ai#side-by-side" class="hash-link" aria-label="Direct link to Side-by-side" title="Direct link to Side-by-side" translate="no">​</a></h2>
<table><thead><tr><th>Dimension</th><th>Customer AI</th><th>Employee AI</th></tr></thead><tbody><tr><td>Audience</td><td>Visitors, shoppers, ticket askers</td><td>Organization members</td></tr><tr><td>Channels</td><td>Website widget, WhatsApp</td><td>Internal Portal</td></tr><tr><td>Auth</td><td>Widget token; optional <code>identify()</code></td><td>Session JWT + Teams / RBAC</td></tr><tr><td>Knowledge</td><td>Customer-safe FAQs and policies</td><td>Internal runbooks and HR/IT</td></tr><tr><td>Risk if mixed</td><td>Internal docs leak publicly</td><td>Unnecessary customer tools on staff chat</td></tr></tbody></table>
<p>Full concept page: <a class="" href="https://docs.qefro.com/docs/concepts/customer-ai-vs-employee-ai">Customer AI vs Employee AI</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="configure-once-deploy-twice">Configure once, deploy twice<a href="https://docs.qefro.com/blog/customer-ai-vs-employee-ai#configure-once-deploy-twice" class="hash-link" aria-label="Direct link to Configure once, deploy twice" title="Direct link to Configure once, deploy twice" translate="no">​</a></h2>
<p>In the Admin Console you:</p>
<ol>
<li class="">Create separate workspaces for Support vs HR/IT.</li>
<li class="">Ingest the right corpus into each.</li>
<li class="">Bind the widget / WhatsApp to Support.</li>
<li class="">Grant portal Members access to internal workspaces via Teams.</li>
</ol>
<p>That is the “configure once, deploy everywhere” model without forcing a single shared index.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-go-next">Where to go next<a href="https://docs.qefro.com/blog/customer-ai-vs-employee-ai#where-to-go-next" class="hash-link" aria-label="Direct link to Where to go next" title="Direct link to Where to go next" translate="no">​</a></h2>
<ul>
<li class="">Customer path: <a class="" href="https://docs.qefro.com/docs/platform/customer-ai">Customer AI</a> → <a class="" href="https://docs.qefro.com/docs/platform/website-widget">Website Widget</a> → <a class="" href="https://docs.qefro.com/docs/platform/whatsapp">WhatsApp</a></li>
<li class="">Employee path: <a class="" href="https://docs.qefro.com/docs/platform/employee-ai">Employee AI</a> → <a class="" href="https://docs.qefro.com/docs/platform/internal-portal">Internal Portal</a> → <a class="" href="https://docs.qefro.com/docs/platform/rbac">RBAC</a></li>
<li class="">Guides: <a class="" href="https://docs.qefro.com/docs/guides/build-ai-customer-support">Build AI Customer Support</a>, <a class="" href="https://docs.qefro.com/docs/guides/create-employee-ai">Create Employee AI</a></li>
</ul>]]></content>
        <author>
            <name>Qefro Team</name>
            <uri>https://qefro.com</uri>
        </author>
        <category label="Product" term="Product"/>
        <category label="Platform" term="Platform"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Hybrid RAG in practice — identifiers meet paraphrases]]></title>
        <id>https://docs.qefro.com/blog/hybrid-rag-in-practice</id>
        <link href="https://docs.qefro.com/blog/hybrid-rag-in-practice"/>
        <updated>2026-07-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Why Qefro combines lexical and vector retrieval for enterprise knowledge — SKUs, error codes, and natural-language questions in one grounded answer path.]]></summary>
        <content type="html"><![CDATA[<p><strong>Hybrid RAG</strong> combines lexical (keyword-oriented) retrieval with vector (semantic) retrieval so assistants can find both exact identifiers and paraphrased questions — then ground answers with citations.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-vectors-alone-struggle-in-enterprise-corpora">Why vectors alone struggle in enterprise corpora<a href="https://docs.qefro.com/blog/hybrid-rag-in-practice#why-vectors-alone-struggle-in-enterprise-corpora" class="hash-link" aria-label="Direct link to Why vectors alone struggle in enterprise corpora" title="Direct link to Why vectors alone struggle in enterprise corpora" translate="no">​</a></h2>
<p>Customer and employee knowledge bases are full of:</p>
<ul>
<li class="">SKUs and part numbers</li>
<li class="">Error codes (<code>E-4421</code>)</li>
<li class="">Policy IDs and ticket prefixes</li>
<li class="">Product names that look like noise to an embedding model</li>
</ul>
<p>Pure semantic search often misses those. Pure keyword search misses “how do I get my money back?” when the doc title is “Refund policy.” Hybrid retrieval covers both.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-fits-the-knowledge-platform">How it fits the Knowledge Platform<a href="https://docs.qefro.com/blog/hybrid-rag-in-practice#how-it-fits-the-knowledge-platform" class="hash-link" aria-label="Direct link to How it fits the Knowledge Platform" title="Direct link to How it fits the Knowledge Platform" translate="no">​</a></h2>
<p>Hybrid RAG is the <strong>retrieval engine</strong>. The <a class="" href="https://docs.qefro.com/docs/concepts/ai-knowledge-platform">AI Knowledge Platform</a> wraps it with ingest, OCR, workspace isolation, and ops.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Question</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  → lexical retriever</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  → vector retriever</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  → fusion / re-rank</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  → grounded generation + citations</span><br></div></code></pre></div></div>
<p>Concept deep dive: <a class="" href="https://docs.qefro.com/docs/concepts/hybrid-rag">Hybrid RAG</a>. Product: <a class="" href="https://docs.qefro.com/docs/platform/knowledge-platform">Knowledge Platform</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quality-loop-we-recommend">Quality loop we recommend<a href="https://docs.qefro.com/blog/hybrid-rag-in-practice#quality-loop-we-recommend" class="hash-link" aria-label="Direct link to Quality loop we recommend" title="Direct link to Quality loop we recommend" translate="no">​</a></h2>
<ol>
<li class=""><strong>Curate sources</strong> — remove duplicate drafts and contradictory wikis.</li>
<li class=""><strong>Test identifier queries</strong> — SKUs, error codes, policy numbers.</li>
<li class=""><strong>Test paraphrase queries</strong> — natural variants of the same intent.</li>
<li class=""><strong>Inspect citations</strong> — wrong citation means fix chunking or source, not only the system prompt.</li>
<li class=""><strong>Refuse when empty</strong> — prefer an honest gap over inventing policy.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="isolation-still-comes-first">Isolation still comes first<a href="https://docs.qefro.com/blog/hybrid-rag-in-practice#isolation-still-comes-first" class="hash-link" aria-label="Direct link to Isolation still comes first" title="Direct link to Isolation still comes first" translate="no">​</a></h2>
<p>Hybrid RAG runs <em>inside</em> a workspace index. Tenancy ensures one organization’s documents never appear in another’s answers. See <a class="" href="https://docs.qefro.com/docs/concepts/multi-tenant-ai-architecture">Multi-tenant AI Architecture</a>.</p>
<p>When live state is required (order status, account balance), pair RAG with <a class="" href="https://docs.qefro.com/docs/concepts/business-actions">Business Actions</a> — docs for policy, APIs for state.</p>]]></content>
        <author>
            <name>Qefro Team</name>
            <uri>https://qefro.com</uri>
        </author>
        <category label="AI" term="AI"/>
        <category label="Engineering" term="Engineering"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Introducing official Qefro documentation]]></title>
        <id>https://docs.qefro.com/blog/introducing-qefro-docs</id>
        <link href="https://docs.qefro.com/blog/introducing-qefro-docs"/>
        <updated>2026-07-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Announcing docs.qefro.com — canonical technical documentation for AI Workspaces, Customer AI, Employee AI, and Business Actions.]]></summary>
        <content type="html"><![CDATA[<p><strong>Qefro Docs</strong> at <a href="https://docs.qefro.com/" target="_blank" rel="noopener noreferrer" class="">docs.qefro.com</a> is the canonical technical documentation for the Qefro AI Workspace Platform.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-we-shipped-a-dedicated-docs-site">Why we shipped a dedicated docs site<a href="https://docs.qefro.com/blog/introducing-qefro-docs#why-we-shipped-a-dedicated-docs-site" class="hash-link" aria-label="Direct link to Why we shipped a dedicated docs site" title="Direct link to Why we shipped a dedicated docs site" translate="no">​</a></h2>
<p>Product marketing on <a href="https://qefro.com/" target="_blank" rel="noopener noreferrer" class="">qefro.com</a> explains <em>what</em> Qefro is. Operators and engineers need <em>how</em>: workspace isolation, hybrid retrieval, Business Tools, RBAC, widget embedding, WhatsApp webhooks, and security boundaries.</p>
<p>We modeled the site after documentation teams trust — clear definitions first, then architecture, workflows, APIs, and honest comparisons.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-will-find">What you will find<a href="https://docs.qefro.com/blog/introducing-qefro-docs#what-you-will-find" class="hash-link" aria-label="Direct link to What you will find" title="Direct link to What you will find" translate="no">​</a></h2>
<table><thead><tr><th>Section</th><th>Start here</th></tr></thead><tbody><tr><td>Concepts (GEO)</td><td><a class="" href="https://docs.qefro.com/docs/concepts/what-is-an-ai-workspace">What is an AI Workspace?</a></td></tr><tr><td>Getting started</td><td><a class="" href="https://docs.qefro.com/docs/getting-started/quick-start">Quick Start</a></td></tr><tr><td>Platform</td><td><a class="" href="https://docs.qefro.com/docs/platform/ai-workspaces">AI Workspaces</a></td></tr><tr><td>Guides</td><td><a class="" href="https://docs.qefro.com/docs/guides/build-ai-customer-support">Build AI Customer Support</a></td></tr><tr><td>API</td><td><a class="" href="https://docs.qefro.com/docs/api/authentication">API Authentication</a></td></tr><tr><td>Security</td><td><a class="" href="https://docs.qefro.com/docs/security/overview">Security Overview</a></td></tr><tr><td>Compare</td><td><a class="" href="https://docs.qefro.com/docs/compare/chatbase-vs-qefro">Chatbase vs Qefro</a></td></tr></tbody></table>
<p>For AI systems and agents, we also publish:</p>
<ul>
<li class=""><a href="https://docs.qefro.com/llms.txt" target="_blank" rel="noopener noreferrer" class="">llms.txt</a> — curated map</li>
<li class=""><a href="https://docs.qefro.com/llms-full.txt" target="_blank" rel="noopener noreferrer" class="">llms-full.txt</a> — full Markdown dump</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-read-the-docs">How to read the docs<a href="https://docs.qefro.com/blog/introducing-qefro-docs#how-to-read-the-docs" class="hash-link" aria-label="Direct link to How to read the docs" title="Direct link to How to read the docs" translate="no">​</a></h2>
<ol>
<li class="">Start with a <strong>definition</strong> page under Concepts if you are evaluating the product.</li>
<li class="">Follow a <strong>guide</strong> when you are implementing a channel or integration.</li>
<li class="">Use <strong>API</strong> and <strong>Security</strong> when you are integrating or reviewing risk.</li>
<li class="">Use search (<code>Ctrl</code> / <code>⌘</code> + <code>K</code>) for exact terms like <code>identify()</code> or webhook paths.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="product-hosts-reference">Product hosts (reference)<a href="https://docs.qefro.com/blog/introducing-qefro-docs#product-hosts-reference" class="hash-link" aria-label="Direct link to Product hosts (reference)" title="Direct link to Product hosts (reference)" translate="no">​</a></h2>
<table><thead><tr><th>Surface</th><th>URL</th></tr></thead><tbody><tr><td>Marketing</td><td><a href="https://qefro.com/" target="_blank" rel="noopener noreferrer" class="">https://qefro.com</a></td></tr><tr><td>Admin Console</td><td><a href="https://app.qefro.com/" target="_blank" rel="noopener noreferrer" class="">https://app.qefro.com</a></td></tr><tr><td>API</td><td><a href="https://api.qefro.com/" target="_blank" rel="noopener noreferrer" class="">https://api.qefro.com</a></td></tr><tr><td>Widget CDN</td><td><a href="https://cdn.qefro.com/widget.js" target="_blank" rel="noopener noreferrer" class="">https://cdn.qefro.com/widget.js</a></td></tr><tr><td>Docs</td><td><a href="https://docs.qefro.com/" target="_blank" rel="noopener noreferrer" class="">https://docs.qefro.com</a></td></tr></tbody></table>
<p>Feedback welcome via <a href="https://qefro.com/contact" target="_blank" rel="noopener noreferrer" class="">contact</a> or <a href="mailto:support@qefro.com" target="_blank" rel="noopener noreferrer" class="">support@qefro.com</a>.</p>]]></content>
        <author>
            <name>Qefro Team</name>
            <uri>https://qefro.com</uri>
        </author>
        <category label="Platform" term="Platform"/>
        <category label="Product" term="Product"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Securing Business Actions in production]]></title>
        <id>https://docs.qefro.com/blog/securing-business-actions</id>
        <link href="https://docs.qefro.com/blog/securing-business-actions"/>
        <updated>2026-07-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Least privilege, encrypted secrets, identity forwarding, SSRF controls, and execution logs for AI assistants that call your APIs.]]></summary>
        <content type="html"><![CDATA[<p><strong>Business Actions</strong> let Customer AI and Employee AI call your REST APIs during a conversation. Treat every action like production API traffic — not like a demo plugin.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-a-business-action-is">What a Business Action is<a href="https://docs.qefro.com/blog/securing-business-actions#what-a-business-action-is" class="hash-link" aria-label="Direct link to What a Business Action is" title="Direct link to What a Business Action is" translate="no">​</a></h2>
<table><thead><tr><th>Term</th><th>Meaning</th></tr></thead><tbody><tr><td><strong>Business Tool</strong></td><td>Connector definition: URL, method, auth, schema</td></tr><tr><td><strong>Business Action</strong></td><td>One runtime invocation of that tool</td></tr></tbody></table>
<p>Concept page: <a class="" href="https://docs.qefro.com/docs/concepts/business-actions">What are Business Actions?</a>. Broader threat model: <a class="" href="https://docs.qefro.com/docs/concepts/ai-agent-security">AI Agent Security</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="controls-that-matter-in-order">Controls that matter in order<a href="https://docs.qefro.com/blog/securing-business-actions#controls-that-matter-in-order" class="hash-link" aria-label="Direct link to Controls that matter in order" title="Direct link to Controls that matter in order" translate="no">​</a></h2>
<ol>
<li class=""><strong>Workspace scope</strong> — tools live inside a workspace; do not attach privileged write tools to a public Customer AI workspace without a hard reason.</li>
<li class=""><strong>Least privilege</strong> — start with read-only <code>GET</code> tools. Add writes only after logging and authz are proven.</li>
<li class=""><strong>Encrypted secrets</strong> — store credentials in the Admin Console; never in browser JS or prompts. See <a class="" href="https://docs.qefro.com/docs/security/secrets">Secrets</a>.</li>
<li class=""><strong>SSRF-aware egress</strong> — tool URLs must not become a path to cloud metadata or internal networks.</li>
<li class=""><strong>Identity forwarding</strong> — for customer-facing tools, use widget <a class="" href="https://docs.qefro.com/docs/platform/identity-forwarding"><code>identify()</code></a> so <em>your</em> API authorizes the end user, not only Qefro’s service credential.</li>
<li class=""><strong>Execution logs</strong> — review unexpected calls as incidents. See <a class="" href="https://docs.qefro.com/docs/security/audit-logs">Audit logs</a>.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="prompt-injection-is-a-blast-radius-problem">Prompt injection is a blast-radius problem<a href="https://docs.qefro.com/blog/securing-business-actions#prompt-injection-is-a-blast-radius-problem" class="hash-link" aria-label="Direct link to Prompt injection is a blast-radius problem" title="Direct link to Prompt injection is a blast-radius problem" translate="no">​</a></h2>
<p>No platform can honestly claim “prompt injection solved.” Design for containment:</p>
<ul>
<li class="">Hostile text may appear in user messages <em>and</em> uploaded documents.</li>
<li class="">Validate tool arguments on your API, not only in the model prompt.</li>
<li class="">Prefer idempotent writes; require human approval for irreversible money movement.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="implementation-path">Implementation path<a href="https://docs.qefro.com/blog/securing-business-actions#implementation-path" class="hash-link" aria-label="Direct link to Implementation path" title="Direct link to Implementation path" translate="no">​</a></h2>
<p>Follow the guide <a class="" href="https://docs.qefro.com/docs/guides/secure-business-actions">Secure Business Actions</a>, then:</p>
<ol>
<li class=""><a class="" href="https://docs.qefro.com/docs/guides/connect-rest-apis">Connect REST APIs</a> or <a class="" href="https://docs.qefro.com/docs/guides/import-openapi">Import OpenAPI</a>.</li>
<li class="">Test the tool in the console before enabling chat invocation.</li>
<li class="">Monitor <code>GET /api/v1/tools/:id/logs</code> (or the console equivalent) during pilot traffic.</li>
</ol>
<p>When in doubt, ship knowledge-only assistants first. Actions can wait until retrieval quality and isolation are solid.</p>]]></content>
        <author>
            <name>Qefro Team</name>
            <uri>https://qefro.com</uri>
        </author>
        <category label="Security" term="Security"/>
        <category label="Engineering" term="Engineering"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Tutorial — from website widget to WhatsApp]]></title>
        <id>https://docs.qefro.com/blog/widget-to-whatsapp</id>
        <link href="https://docs.qefro.com/blog/widget-to-whatsapp"/>
        <updated>2026-07-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Ship Customer AI on the website first, validate retrieval quality, then add WhatsApp on Growth+ using the same Support workspace.]]></summary>
        <content type="html"><![CDATA[<p>Ship <strong>Customer AI</strong> on the website first, validate retrieval quality, then add WhatsApp on Growth+ — preferably bound to the same Support workspace so answers stay consistent.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-website-first">Why website first<a href="https://docs.qefro.com/blog/widget-to-whatsapp#why-website-first" class="hash-link" aria-label="Direct link to Why website first" title="Direct link to Why website first" translate="no">​</a></h2>
<p>The website widget is the fastest loop for:</p>
<ul>
<li class="">Citation quality on real FAQs</li>
<li class="">Refusal behavior when knowledge is missing</li>
<li class="">Branding and tone</li>
<li class="">Optional <code>identify()</code> before any Business Tools</li>
</ul>
<p>WhatsApp adds Meta Cloud API setup, webhook verification, and plan limits. Validate the brain before you multiply channels.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1--create-a-support-workspace">Step 1 — Create a Support workspace<a href="https://docs.qefro.com/blog/widget-to-whatsapp#step-1--create-a-support-workspace" class="hash-link" aria-label="Direct link to Step 1 — Create a Support workspace" title="Direct link to Step 1 — Create a Support workspace" translate="no">​</a></h2>
<ol>
<li class="">Sign in at <a href="https://app.qefro.com/" target="_blank" rel="noopener noreferrer" class="">app.qefro.com</a>.</li>
<li class="">Create a workspace named for Support.</li>
<li class="">Upload policies and FAQs (or crawl approved URLs).</li>
<li class="">Ask ten real customer questions and check citations.</li>
</ol>
<p>Guides: <a class="" href="https://docs.qefro.com/docs/getting-started/quick-start">Quick Start</a>, <a class="" href="https://docs.qefro.com/docs/guides/build-ai-customer-support">Build AI Customer Support</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2--embed-the-website-widget">Step 2 — Embed the website widget<a href="https://docs.qefro.com/blog/widget-to-whatsapp#step-2--embed-the-website-widget" class="hash-link" aria-label="Direct link to Step 2 — Embed the website widget" title="Direct link to Step 2 — Embed the website widget" translate="no">​</a></h2>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">script</span><span class="token tag" style="color:#00009f"></span><br></div><div class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://cdn.qefro.com/widget.js</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></div><div class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">data-token</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">YOUR_WIDGET_TOKEN</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></div><div class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">data-endpoint</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://api.qefro.com</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></div><div class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">data-workspace-id</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">YOUR_WORKSPACE_ID</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token script language-javascript"></span><br></div><div class="token-line" style="color:#393A34"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></div></code></pre></div></div>
<p>Full guide: <a class="" href="https://docs.qefro.com/docs/guides/deploy-website-widget">Deploy Website Widget</a>. Platform notes: <a class="" href="https://docs.qefro.com/docs/platform/website-widget">Website Widget</a>.</p>
<p>If Business Tools need the logged-in shopper or account holder, add <a class="" href="https://docs.qefro.com/docs/platform/identity-forwarding"><code>identify()</code></a> after your existing session is established.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3--add-whatsapp-growth">Step 3 — Add WhatsApp (Growth+)<a href="https://docs.qefro.com/blog/widget-to-whatsapp#step-3--add-whatsapp-growth" class="hash-link" aria-label="Direct link to Step 3 — Add WhatsApp (Growth+)" title="Direct link to Step 3 — Add WhatsApp (Growth+)" translate="no">​</a></h2>
<ol>
<li class="">Confirm your plan includes WhatsApp.</li>
<li class="">Configure Meta Cloud API credentials in the Admin Console.</li>
<li class="">Point Meta’s webhook to Qefro’s WhatsApp webhook path on <code>api.qefro.com</code>.</li>
<li class="">Bind the same Support workspace you already validated.</li>
</ol>
<p>Guide: <a class="" href="https://docs.qefro.com/docs/guides/deploy-whatsapp-ai">Deploy WhatsApp AI</a>. Platform: <a class="" href="https://docs.qefro.com/docs/platform/whatsapp">WhatsApp</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-4--keep-audiences-separate">Step 4 — Keep audiences separate<a href="https://docs.qefro.com/blog/widget-to-whatsapp#step-4--keep-audiences-separate" class="hash-link" aria-label="Direct link to Step 4 — Keep audiences separate" title="Direct link to Step 4 — Keep audiences separate" translate="no">​</a></h2>
<p>Customer AI (widget + WhatsApp) should not share an HR or payroll workspace. See <a class="" href="https://docs.qefro.com/docs/concepts/customer-ai-vs-employee-ai">Customer AI vs Employee AI</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="done-when">Done when<a href="https://docs.qefro.com/blog/widget-to-whatsapp#done-when" class="hash-link" aria-label="Direct link to Done when" title="Direct link to Done when" translate="no">​</a></h2>
<ul>
<li class="">Website answers cite the right sources</li>
<li class="">Unknown topics refuse cleanly</li>
<li class="">WhatsApp replies match website quality for the same questions</li>
<li class="">Tools (if any) are logged and least-privileged</li>
</ul>
<p>Next: <a class="" href="https://docs.qefro.com/docs/guides/production-deployment">Production Deployment</a>.</p>]]></content>
        <author>
            <name>Qefro Team</name>
            <uri>https://qefro.com</uri>
        </author>
        <category label="Tutorials" term="Tutorials"/>
        <category label="Product" term="Product"/>
    </entry>
</feed>