Tools kan använda en intern AI-motor ("OpenAI Engine") för att analysera innehåll och driva plattformsfunktioner – utan att någon API-nyckel någonsin exponeras i frontend.
Den här dokumentationen är en användarmanual och beskriver:
401-, 403- och 422-felPlattformen gör nu en medveten skillnad mellan:
Den skillnaden är viktig eftersom de inte är samma sak.
Viktigt: POST /api/ai/socialgpt/respond är inte den huvudsakliga/generella "respond"-endpointen i Tools. Den finns för SocialGPT / Social Media Tools-kontraktet. Interna runtimes som IRCWatch ska normalt använda POST /api/ai/internal/respond i stället.
ai.socialgpt (ai.client finns kvar som legacy-alias)provider_socialgpt (äldre tools_ai_bearer-rader fungerar fortfarande), men den faktiska runtime-autentiseringen följer nu tokenens scope i stället för providernamnet i sig/keys/mine) och adminkön /admin/openaiURL:
/admin/openaiKrav:
openai.manageI webgränssnittet kan du:
Model-dropdowns i /admin/openai är inte längre hårdkodade.
GET /v1/modelsallowed_models är satt så filtreras dropdownen vidare av allowlistenDet betyder att modellistan i admin bättre speglar vad den aktiva provider-nyckeln faktiskt kan använda, utan att någon nyckel exponeras i webbläsaren.
503, beroende på endpoint).Obs: Provider-nycklar hanteras under API Keys och visas aldrig i klartext.
Om Slack-audit-forwarding är aktiverad för OpenAI- / SocialGPT-kategorier innehåller auditposterna nu också:
user_id, och namn/e-post när det finns)error_reason när ett upstream-/provideranrop misslyckasDet gör det lättare för operatörer att se vem som utlöste ett AI-anrop och varför en misslyckad request avvisades.
Användare som har behörighet kan skapa en eller flera personliga bearer-token i Tools:
/keys/mine/keys/mine visar nu de kända access scopes i Tools som en checkboxlista i stället för att användaren själv ska behöva gissa scopens namn manuelltDessa Tools-baserade AI-klienttoken är:
ai.socialgpt, ai.internal osv.), så provider/namn är bara label/kategoriDet gör att du kan ha en token per uppdrag (till exempel en intern automation, ett batchjobb eller en research-klient) utan att återanvända samma bearer-token överallt.
Tools har fortfarande också ett separat dedikerat tokenflöde för SocialGPT:
provider_socialgpt-rad för bekvämlighettools_ai_bearer fungerar fortfarande för kompatibilitetai.socialgptAnvänds så här:
Authorization: Bearer <token>
Varje token fungerar bara för de endpoints som täcks av tokenens egna access scopes och är kopplad till din användare + behörighet.
De inbyggda access scopes som nu visas i My API Keys är:
ai.socialgptai.internalwhisper.apimail-support-assistant.relaysms.sendsms.gatewayTools stöder nu också andra personliga systemtoken (till exempel provider_ircwatch eller provider_mail_support_assistant) så länge de är:
is_ai=1) och/eller tilldelade det explicita scopet ai.socialgptViktig skillnad:
provider_openai är uppströmsproviderns secret som används mot OpenAI och behandlas aldrig som en AI-mottagartokenOm du ska integrera en klient mot Tools AI, börja här.
Börja inte med att klistra in en slumpmässig AI-URL i en klient och hoppas att den beter sig som OpenAI:s publika API.
Tools har i dag flera AI-relaterade endpoints med olika kontrakt:
| Användningsfall | Endpoint | Token-scope | Viktig notering |
|---|---|---|---|
| SocialGPT-liknande reply / verify / modify-flöde | POST /api/ai/socialgpt/respond |
ai.socialgpt |
Detta är ett Tools-specifikt kontrakt, inte ett OpenAI-kompatibelt |
| Intern runtime / assistent / automation | POST /api/ai/internal/respond |
ai.internal |
Kräver client_slug och minst context eller user_prompt |
| IRCWatch / server-side-botruntime | POST /api/ai/internal/respond |
ai.internal |
Använd helst en intern client slug som ircwatch; behandla inte SocialGPT som standardendpoint för runtime-flöden |
| Analys av en fjärr-URL server-side | POST /api/ai/url/analyze |
godkänd OpenAI-access för den autentiserade användaren | Inte tänkt som en generell chat-endpoint |
| Validera bara en SocialGPT-liknande bearer-token | GET /api/social-media-tools/extension/validate-token |
ai.socialgpt |
Kontrollerar tokenen, inte om användaren faktiskt får köra OpenAI |
Det här är den vanligaste integrationsmissen.
Tools-endpoints som:
POST /api/ai/socialgpt/respondPOST /api/ai/internal/respondär inte drop-in-ersättare för OpenAI /v1/chat/completions.
Det betyder att:
POST /api/ai/internal/respond kräver Tools-specifika fält som client_slugOm klienten inte kan styra JSON-body själv kan den behöva en adapter/proxy i stället för direktkoppling mot den interna Tools-endpointen.
För bearer-tokenintegrationer finns två separata kontroller som måste vara uppfyllda:
Exempel:
ai.internal men ändå nekas med 403 om användaren bakom tokenen saknar godkänd OpenAI-accessvalidate-token men ändå misslyckas på ett riktigt AI-anrop eftersom användaren bakom tokenen saknar provider_openaiInnan du felsöker en browser extension, Copilot-liknande inställningsruta eller desktopklient, testa samma endpoint manuellt med curl eller annan rå HTTP-klient.
Det svarar direkt på:
Använd:
POST /api/ai/socialgpt/respondnär klienten kan skicka Tools-specifika fält som:
contextuser_promptmodifierrequest_modeclient_name, client_version, client_platform)Använd:
POST /api/ai/internal/respondnär klienten kan skicka en Tools-specifik JSON-body som innehåller:
client_slugcontext eller user_promptDet här är normalvalet för Tools-baserade runtimes som IRCWatch, cron-jobb, bakgrundsarbetare och andra integrationer som inte är SocialGPT.
Utgå inte från att POST /api/ai/internal/respond är rätt URL.
Om klienten bara kan skicka OpenAI-standardformat som messages[], input eller vanlig Chat Completions-payload behöver du i dagsläget i stället något av följande:
Utan den adaptern kan klienten fallera med 422 Unprocessable Content trots att tokenen är korrekt.
Vanliga nya användare får inte längre använda OpenAI-baserade Tools-funktioner automatiskt bara för att ett dagligt budgettak finns.
Användarflöde:
/keys/mine/openai/access/request direkt i webbläsaren skickar Tools dig nu tillbaka till den inbyggda ansökningsrutan under My API Keys i stället för att lämna dig på en generisk felsida/openai/access/requst/admin/openaiprovider_openai och kan därefter skapa en eller flera Tools OpenAI forwarder-token under My API KeysAdminflöde:
/admin/openai/admin/openaiprovider_tools_openai-token, inte bara den äldre Tools AI bearer-raden)Endpoint:
POST /api/ai/url/analyzeSyfte:
Form data eller JSON:
url (required) — URL att analyseraquestion (optional) — fråga/fokus för analysenprofile (optional) — prompt-profil (default: URL Analyzer om den finns, annars minimal default)JSON:
ok — true/falserequest_id — intern request-idlatency_ms — ungefärlig svarstidmodel — vilken modell som användesresponse — model output (om ok)error — felmeddelande (om ok=false)För att använda endpointen krävs:
401 Unauthenticatedis_admin=1) → tillåts alltidprovider_openaiOm OpenAI provider saknas (ingen global provider_openai API key) returneras normalt 503.
Endpoint:
POST /api/ai/socialgpt/respondAuth / access-regler:
ai.socialgpttools_ai_bearer / provider_socialgpt-rader fungerar fortfarande eftersom de bakfylls till samma scopeapi_keys.is_ai=1), eftersom den äldre flaggan fortfarande tolkas som ai.socialgptprovider_openai)Om bearer-token tillhör en användare utan godkänd OpenAI-access returnerar endpointen 403.
Additiva requestfält för SocialGPT:
client_nameclient_versionclient_platformDe här fälten är valfria och låter Tools identifiera vilken klientbuild som gjorde requesten. Svaret kan också innehålla ett additivt client-objekt som ekar tillbaka accepterade metadata.
Notering om felhantering:
error som vanlig text.Säkerhetsbeteende:
.env-värden, lösenord, token, API-nycklar eller andra interna Tools-detaljer.Endpoint:
POST /api/ai/internal/respondSyfte:
dnsbl-engine gå direkt mot den centrala OpenAI-motorn i stället för att ärva SocialGPT-lagrets inställningarclient_slug som identifierare så att defaultvärden, auditering och användningsstatistik kan kopplas till rätt anropare i /admin/openaiai.internal, så att en intern körning kan roteras eller stängas av utan att påverka andraAuth / access-regler:
ai.internalprovider_openai)Viktig kompatibilitetsnotering:
Requestfält:
client_slug (required) — anroparidentifierare som mail_support_assistant_standalone, mail_support_assistant_tools_admin, dnsbl_engine eller vilken annan stabil icke-tom slug som integrationen själv väljercontext (optional) — stödjande kontext/body-datauser_prompt (optional) — den direkta instruktionen för uppgiftenmodifier (optional) — kort uppföljande modifieraremood / custom_mood (optional) — tonalitetsoverride för just det här anropet ovanpå sparad klientconfigresponder_name_override (optional)persona_profile_override (optional)custom_instruction_override (optional)model (optional)reasoning_effort (optional) — none|low|medium|high|xhighresponse_language (optional) — auto|sv|en|da|no|de|fr|esmax_tokens (optional)temperature (optional)use_web_search (optional)web_search_required (optional)Valideringsregel som orsakar många 422-svar:
client_slug är obligatorisktcontext eller user_prompt måste vara icke-tomViktig runtime-notering:
/admin/openaiclient_slug som identifierareSå en payload som denna fallerar:
{
"model": "gpt-4"
}
med ett valideringsliknande 422 / “unprocessable content”-svar.
{
"client_slug": "client_browser_companion",
"user_prompt": "Reply with ok",
"context": "Connection test"
}
curl -X POST "https://tools.tornevall.net/api/ai/internal/respond" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"client_slug": "client_browser_companion",
"context": "Temporary demo feature",
"user_prompt": "Reply with ok",
"model": "gpt-4o",
"response_language": "en"
}'
Lyckat svar innehåller:
okrequest_idmodelresponseusageused_fallback_modelclient (slug, name, description)applied_settings (responder_name, persona_profile_excerpt, custom_instruction_excerpt, mood, response_language, reasoning_effort)web_search-metadata (requested, required, used, citations[])Admin-UI-notering:
/admin/openai har nu också en central sektion Internal AI clients där operatörer kan redigera sparade standardvärden för varje internt client_slug, även sådana slugs som först dök upp via live-trafik.För interna assistentliknande klienter ligger den huvudsakliga styrningen inte i URL:en i sig.
Beteendet kommer från två lager:
client_slug (när en sådan finns)Det normala sättet att “instruera Copilot för den här assistenten” är därför att:
client_slug för den aktuella runtimen/admin/openai om du vill ha sparade defaultvärden/statistik därresponder_name_overridepersona_profile_overridecustom_instruction_overridemoodresponse_languageOm det externa klient-UI:t inte låter dig skicka dessa extra fält är begränsningen i den klienten — inte i själva Tools-tokenen.
401 UnauthenticatedBrukar betyda:
403 ForbiddenBrukar betyda:
provider_openai)Detta är inte samma sak som “dålig token”.
422 Unprocessable ContentBrukar betyda:
För POST /api/ai/internal/respond är det vanligast att något av detta är orsaken:
client_slug saknascontext och user_prompt är tommaDet är väntat om du bara testade:
GET /api/social-media-tools/extension/validate-tokenför den endpointen verifierar bara tokenen i sig.
Den bevisar inte att användaren faktiskt får köra OpenAI-baserade requester just nu.
För en ny integration, testa i den här ordningen:
curl-request mot den riktiga mål-endpointen med minsta giltiga payloadDen här sektionen är avsiktligt bara en designskiss.
Den beskriver en rekommenderad riktning för en framtida Tools-side kompatibilitetsadapter så att externa klienter som bara förstår OpenAI-liknande requestformat ändå kan prata med Tools utan att själva behöva skicka dagens Tools-specifika client_slug / context / user_prompt-payload direkt.
Den här endpointen finns inte ännu som ett publikt kontrakt.
Vissa klienter stöder bara fält som:
modelmessages[]temperaturemax_tokensoch ett enda textfält för ungefär “provider URL”.
Sådana klienter kan inte enkelt prata med:
POST /api/ai/internal/respondeftersom den interna Tools-endpointen förväntar sig fält som:
client_slugcontextuser_promptEn adapter-endpoint skulle lösa den mismatchen.
Föreslagen framtida endpoint:
POST /api/openai/v1/chat/completionsFöreslagen authmodell:
ai.internalFöreslaget backendbeteende:
client_slug från någon av dessa källor:
client_slugX-Tools-Client-Sluggeneric_openai_compat_clientmessages[] till internt Tools-format:
system / developer / assistenthistorik → contextuser-meddelandet → user_promptmodeltemperaturemax_tokensPOST /api/ai/internal/respond{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": "Sammanfatta den här sidan i tre punkter."
}
]
}
Det här är valfria idéer för en framtida adapter. De är inte aktiva publika API-fält idag.
{
"client_slug": "generic_openai_compat_client",
"response_language": "en",
"tools_context": "Temporary browser-side assistant session"
}
För maximal kompatibilitet bör svaret strukturellt ligga nära OpenAI Chat Completions, till exempel:
{
"id": "tools-chatcmpl-123",
"object": "chat.completion",
"created": 1760000000,
"model": "gpt-4o",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 100,
"completion_tokens": 40,
"total_tokens": 140
}
}
Om adaptern implementeras senare, håll felsemantiken tydlig:
401 → saknad/ogiltig token403 → token accepterad, men användaren bakom tokenen saknar OpenAI-access422 → saknad messages[], saknat användbart user-meddelande eller misslyckad klientupplösning503 → Tools OpenAI Engine/provider otillgängligOm det byggs senare är den renaste riktningen normalt:
app/Http/Controllers/AiGatewayController.phproutes/api.phpInternalOpenAiClientServiceSnippetarna nedan är avsiktligt generiska. De är inte beroende av en viss intern klient som client_browser_companion.
Byt ut platshållare som:
YOUR_API_TOKENYOUR_CLIENT_SLUGYOUR_TEXT_HEREmot värden som passar din egen Tools-konfiguration.
{
"client_slug": "YOUR_CLIENT_SLUG",
"user_prompt": "YOUR_TEXT_HERE",
"context": "Valfri stödjande kontext"
}
curl-exempelcurl -X POST "https://tools.tornevall.net/api/ai/internal/respond" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"client_slug": "generic_internal_assistant",
"context": "Valfri sid- eller arbetsflödeskontext.",
"user_prompt": "Sammanfatta de viktigaste åtgärderna från den här sidan.",
"model": "gpt-4o",
"response_language": "en"
}'
const response = await fetch("https://tools.tornevall.net/api/ai/internal/respond", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
},
body: JSON.stringify({
client_slug: "generic_internal_assistant",
context: "Valfri sid- eller arbetsflödeskontext.",
user_prompt: "Sammanfatta de viktigaste åtgärderna från den här sidan.",
model: "gpt-4o",
response_language: "en"
})
});
const data = await response.json();
console.log(data);
$headers = @{
"Content-Type" = "application/json"
"Authorization" = "Bearer YOUR_API_TOKEN"
}
$body = @{
client_slug = "generic_internal_assistant"
context = "Valfri sid- eller arbetsflödeskontext."
user_prompt = "Sammanfatta de viktigaste åtgärderna från den här sidan."
model = "gpt-4o"
response_language = "en"
} | ConvertTo-Json
Invoke-RestMethod \
-Method Post \
-Uri "https://tools.tornevall.net/api/ai/internal/respond" \
-Headers $headers \
-Body $body
import requests
response = requests.post(
"https://tools.tornevall.net/api/ai/internal/respond",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN",
},
json={
"client_slug": "generic_internal_assistant",
"context": "Valfri sid- eller arbetsflödeskontext.",
"user_prompt": "Sammanfatta de viktigaste åtgärderna från den här sidan.",
"model": "gpt-4o",
"response_language": "en",
},
timeout=60,
)
print(response.status_code)
print(response.json())
/admin/openai-instruktionsmall för interna assistenterOm du skapar en intern assistentprofil i /admin/openai är den här generiska startmallen ofta en bättre första nivå än att direkt hårdkoda en klientspecifik persona.
Använd den här stilen för assistenter som ska:
Du är en praktisk intern assistent för Tools-anslutna klienter.
Din uppgift är att hjälpa användaren att förstå den skickade kontexten, sammanfatta viktig information, skriva om eller förtydliga text och föreslå användbara nästa steg.
Prioriteringar:
1. Var tydlig och operativt användbar.
2. Föredra korta, direkta svar om inte användaren uttryckligen ber om mer detalj.
3. När du sammanfattar, fokusera på de viktigaste fakta, beslut, blockerare, deadlines och actions.
4. Om den skickade kontexten är ofullständig, säg vad som saknas i stället för att hitta på detaljer.
5. Påstå inte att du har klickat, hämtat, verifierat eller inspekterat något utanför den skickade kontexten.
6. Om användaren ber om en omskrivning, bevara betydelsen men förbättra struktur, ton och tydlighet.
7. Om användaren frågar vad nästa steg är, ge en kort ordnad lista med åtgärder.
Ton:
- lugn
- kompetent
- hjälpsam
- inte överdrivet pratig
Undvik:
- hype
- vag konsultprosa
- att presentera osäker information som verifierad sanning
- långa introduktioner eller avslutande utfyllnad om inte användaren vill ha mer formell stil
Ett bra generiskt startvärde i /admin/openai är:
clear, concise, practicalRelaterade extension-endpoints:
GET /api/social-media-tools/extension/validate-tokenGET /api/social-media-tools/extension/testPOST /api/social-media-tools/extension/testViktig skillnad:
validate-token verifierar bara att den skickade personliga AI-kapabla tokenen är giltigtest kör ett riktigt OpenAI-baserat smoke test och kräver därför godkänd OpenAI-access för icke-adminDet gör att klienter kan skilja på "tokenet tillhör en riktig användare" och "den användaren får faktiskt köra OpenAI-anrop just nu".
curl -X POST "https://tools.tornevall.net/api/ai/url/analyze" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-d '{
"url": "https://example.com",
"question": "What is this page about?",
"profile": "URL Analyzer"
}'
Endpoint:
GET /api/social-media-tools/extension/modelsSyfte: