Message Tagging
Message tags (semantic tags) detect and respond to specific types of user messages. New tags use the Jev classifier engine (TypeSafe System One). Older tags use an embedding classifier engine. Covers Jev data flow, privacy, and retention

Message tags are one of the most powerful features in Chipp. They let you automatically detect specific types of messages and take action, whether that’s routing to a human, blocking harmful content, or tracking purchase intent.
What Can You Do with Tags?
Tags unlock a wide range of automation possibilities. Here are just a few:
🏷️ What Can You Do with Tags?
How Tag Detection Works
Unlike simple keyword matching, Chipp understands the meaning behind messages. New tags use the Jev classifier: Jev decides from the tag’s name and description, so a new tag works right away with no example phrases. Tags created before Jev use semantic similarity against their example phrases. Either way, your tags catch variations and paraphrases you never explicitly defined.
See Tag Detection in Action
Type a message and see which tags would be detected based on semantic similarity.
Demo uses pre-computed results for illustration
Why Semantic Matching Matters
Traditional keyword-based systems require you to anticipate every possible way someone might phrase a request. With semantic matching:
- “I want to talk to a human” matches “Can I speak with a real person?”
- “What’s the price?” matches “How much does this cost?”
- “I’m frustrated” matches “This is really annoying”
You define a few example phrases, and the AI understands the underlying intent.
Getting Started
Ready to set up your first tag? Follow this step-by-step guide:
Open the app where you want to configure message tags.
Click on "Tags" in the setup section to manage your tag definitions.
Create tags with names and descriptions. The AI uses descriptions to determine when to apply each tag.
Chat with your app and verify tags are applied correctly. Adjust descriptions as needed.
Tag Configuration Options
Each tag has several settings you can customize:
Tag Name
Give your tag a clear, descriptive name. You’ll see this in your analytics and when reviewing chat history, so make it easy to understand at a glance.
Good names: “Human Escalation”, “Pricing Question”, “Complaint” Bad names: “Tag 1”, “Important”, “Check”
Description
Describe exactly when the tag should trigger. For new (Jev) tags, Jev decides from the name and this description, so be specific.
Example Phrases
Add 3-5 phrases under “TRAIN THIS TAG · POSITIVE EXAMPLES” that represent the type of message you want to detect. Older similarity-based tags need these to work. For Jev tags they are optional boundary material. Focus on variety:
Good examples for "Human Needed":
- "I need to talk to a human"
- "Can I speak with a real person?"
- "Connect me to support"
- "I want to talk to someone"
Less effective (too similar):
- "Talk to human"
- "Speak to human"
- "Human please"
- "Get me a human"Detection Sensitivity
The “Detection sensitivity” slider runs from Strict to Sensitive and controls how readily the tag triggers. A higher percentage means the tag triggers more readily:
| Slider | Label | Trade-off |
|---|---|---|
| 0-29% | Very strict | Precise matching only, may miss variations |
| 30-69% | Balanced | Good starting point |
| 70-100% | Very sensitive | Catches more variations, more false positives |
Tip: New tags start at 50% (Balanced). Adjust based on what you see in your chat history.
Static Text Response (Optional)
For safety or compliance tags, you can replace the AI’s response entirely when a tag is detected. Enter the text in the “Static text response” field (leave it empty to use the AI response). You can also turn on “Freeze conversation” to disable input after the static response. This is useful for:
- Harmful content: Block and provide a polite refusal
- Off-topic requests: Redirect to your app’s purpose
- Sensitive topics: Provide specific guidance or disclaimers
When you add a static text response, the AI won’t generate anything: your exact text will be shown instead.
Best Practices
Start Small
Begin with 2-3 high-value tags rather than trying to cover every scenario. You can always add more as you learn what your users are asking.
Review Matches Regularly
Check your tag matches in the chat history to spot false positives and missed detections. This helps you tune your sensitivity and add better example phrases.
Use Specific Examples
The more specific and varied your example phrases, the better the detection. Generic phrases lead to more false positives.
Don’t Over-Block
Only use blocking responses when absolutely necessary. For most tags, it’s better to let the AI respond naturally while you track the conversation.
Common Tag Configurations
Here are some popular tag setups to get you started:
Customer Support Bot
| Tag | Purpose | Blocking? |
|---|---|---|
| Human Needed | Route frustrated users to support | No |
| Refund Request | Flag for manual review | No |
| Positive Feedback | Track happy customers | No |
Sales Assistant
| Tag | Purpose | Blocking? |
|---|---|---|
| Purchase Intent | Identify hot leads | No |
| Pricing Question | Track interest | No |
| Competitor Mention | Monitor positioning | No |
Knowledge Base
| Tag | Purpose | Blocking? |
|---|---|---|
| Off-Topic | Redirect to purpose | Yes |
| Complex Question | Flag for follow-up | No |
| Feedback | Collect suggestions | No |
Viewing Tag Analytics
Once your tags are active, you can see them in action:
- Chat History: Each message shows any tags that were detected
- Tag Detail View: Click on a tag to see all matches, sorted by recency
- Remove False Positives: Click the X on any incorrectly tagged message to improve future detection
Advanced Tips
Combine with Custom Actions
Use tags as triggers for more complex workflows. When a tag is detected, you could:
- Send a notification to Slack
- Create a ticket in your CRM
- Update a spreadsheet
- Trigger an email
Multiple Tags per Message
A single message can trigger multiple tags. For example, “I want a refund and need to speak to someone” might trigger both “Refund Request” and “Human Needed.”
Tag Categories
Organize related tags with consistent naming prefixes:
Support: Human NeededSupport: ComplaintSales: Pricing QuestionSales: Demo Request
Negative Examples: Teaching Tags What NOT to Match
By default, tags learn only from positive examples: phrases that should trigger. For most use cases this works well, but when your tag guards a hard compliance boundary (like “block external data comparisons” or “prevent off-label claims”), a legitimate message can look almost identical to a prohibited one.
When to Use Negative Examples
Negative examples are most valuable in three scenarios:
- Semantic Overlap: Your positive examples (“Compare our rate to published literature”) are semantically very similar to legitimate messages (“Compare our rate across patient subgroups”). Raising the sensitivity threshold alone can’t separate them.
- Compliance Boundaries: Tags that guard strict regulatory or safety rules where false negatives (missing a prohibited intent) are worse than false positives, but missed legitimate uses break user experience.
- Calibration Precision: You’ve tuned a tag with “Test a message” (see below) and consistently see one type of false positive that thresholds can’t filter.
How Negative Examples Work
This section describes tags that use the embedding classifier (older tags). For a tag that uses the Jev classifier, Chipp sends the positive and negative examples to Jev as context, and Jev returns a confidence score. The “tie triggers the tag” rule below does not apply to Jev tags. The rest of this section explains the embedding classifier.
Chipp’s semantic matching computes cosine similarity between an incoming message and all your tag’s examples, both positive and negative. A message triggers the tag if its best match (highest similarity to any example) beats the configured threshold.
Key insight: Negative examples compete directly against positive examples in the same semantic space. When a message is semantically close to both a positive and a negative example, the tag resolves toward whichever example it’s more similar to. This is why a couple of well-chosen negatives can improve precision where thresholds alone cannot.
Guardrail: If a message is equally similar to a positive and negative example (a tie), the tag triggers: fail-safe behavior. When in doubt, block.
Example: Pharma Compliance Boundary
A tag needs to block external/published-literature comparisons (“What is our rate compared to the published literature?”) while allowing legitimate cohort analyses:
Positive examples (must trigger):
- “How does our rate compare to published literature?”
- “What does the literature say about this rate?”
- “How do we stack up against industry benchmarks?”
Negative examples (must NOT trigger):
- “How does our rate differ across patient subgroups?”
- “Compare our rate between males and females in the cohort”
- “What’s the misdiagnosis rate in our patient population?”
With the negatives in place, the classifier learns that “compare … to literature/benchmarks/external” is the true signal, not comparison in general. Testing revealed that this fixture (6 prompts at 0.33 and 0.5 sensitivity thresholds) achieves clean separation only with negatives. Thresholds alone catch either all positives and all negatives, or none of either.
Creating and Managing Negative Examples
- Open the tag editor and scroll to “NEGATIVE EXAMPLES · MUST NOT TRIGGER”
- Add 2-5 phrases that are similar to your positives but must never trigger
- Focus on the specific semantic boundary you’re guarding (e.g., “external comparisons” vs. “within-cohort comparisons”)
- Use “Test a message” (below) to validate that your negatives actually prevent false positives
- If separability still isn’t clean, add more negatives targeting the boundary, or split into more specific tags
Prefab and Custom Examples: What a Tag Really Uses
A tag can classify with two kinds of example phrases. Both count. Tools and the API call example phrases “utterances”, so you may see “prefab utterances” and “custom utterances”. These tag examples are the same thing.
| Origin | Where it comes from | Polarity | Editable |
|---|---|---|---|
prefab_template | Shared starter examples that Chipp ships for well-known tag names (for example “Sexual Content”). Every app with a tag of that name gets them. | Always positive | No. Read-only from your app |
app_custom | Phrases you or your tools added to this app’s tag | Positive, or negative (a boundary example that must not trigger) | Yes |
If your tag name matches a prefab tag, the prefab examples apply even when you added no phrases yourself. They can move a score. A harmless message can score above zero against a large prefab set. This is why a tag can seem to react to a message when its custom example list looks empty.
The custom list alone is not the full input of the classifier. Always read the combined set (see below) before you tune a tag.
Inspect the Combined Set
Use list_tag_examples with a tag_id. It returns every example the tag classifies with:
origin:prefab_templateorapp_custompolarity:positiveornegativeeditable:falsefor prefab examples,truefor custom onescounts: the number of examples per origin, for example{ "prefabTemplate": 124, "appCustom": 3 }
Use the type option to show only positive or only negative examples. The counts still cover the whole set.
list_tags shows the same per-origin counts for every tag in an app, in example_counts. Its positive_examples and negative_examples lists hold only your custom phrases. Use the counts to see when prefab examples apply, then call list_tag_examples to read them.
You can only change or delete app_custom examples (update_tag_example, delete_tag_example).
Export the Combined Set
Call list_tag_examples with format: "csv". The CSV holds the same rows as the list call, with origin, polarity and editable columns. Every cell is quoted. A cell that starts with =, +, - or @ is changed so that a spreadsheet does not run it as a formula.
Prefab Examples and Jev Tags
New tags use the Jev classifier. Jev decides from the tag’s name and description. Prefab examples stay active for a Jev tag whose name matches a prefab tag. We made this decision on purpose:
- Jev receives the prefab examples as positive criteria, together with your custom examples. Jev reads at most 20 positive and 20 negative examples per tag.
- If Jev is not available, the tag falls back to embedding similarity, and the prefab examples are the data for that fallback.
- Chipp removed nothing. No prefab example was deleted or turned off.
If you want a tag with no prefab influence, give it a name that does not match a prefab tag.
Tag Testing: Which Tools Classify a Message
Some tools only read or edit tags. Some send a message through the real classifier. Use this table to pick the right one for tag testing.
| Tool or panel | Classifies the message? | What it classifies | Why |
|---|---|---|---|
chat_with_app | Yes | The user message of each call. Never the assistant reply | It runs the real chat flow and saves a real conversation, like every other chat surface |
log_chat_message | Yes, unless you set detect_tags to false | The first user message in the call | It records a conversation from another system and treats it as real traffic |
| ”Test a message” panel in the tag editor | Scores only | The text you type | A diagnostic. It records nothing and sends no reply |
create_tag, update_tag, add_tag_examples, set_tag_examples | No | Nothing | They change the tag. The next message uses the new setup |
list_tags, list_tag_examples, list_tag_instances | No | Nothing | Read only |
Notes for both chat tools:
- Classification runs in the background. It never slows down or fails the chat turn.
- Apps in zero data retention mode are skipped. Chipp does not store content-derived data for these apps.
- A blank message is skipped.
- A match appears in
list_tag_instancesand in the chat history, and can start the tag’s notifications.
Earlier versions of chat_with_app did not classify messages. A conversation you started with it in the past has no tags from it. Send the message again to classify it.
A Short Tag Testing Workflow
- Call
list_tagsand readexample_countsfor the tag. - Call
list_tag_examplesto read the full set, prefab examples included. - Send a test message with
chat_with_app, or log one withlog_chat_message. - Call
list_tag_instancesto see if the tag matched. - Add a negative example for a false positive, or a positive example for a miss, and test again.
Calibrating Tags with “Test a Message”
The “Test a message” panel in the tag editor lets you score any message against the tag in real-time, showing:
- Match score: Numeric similarity (0-1) to the closest example
- Threshold: Your configured sensitivity level
- Would trigger: Boolean outcome for this message
This is invaluable for calibration:
- Draft your positives and negatives, then test real prompts from your chat history
- If a legitimate message is scoring too high (near the threshold), add a negative example close to it
- If a prohibited message is scoring too low (missing true positives), refine your positive examples for more specificity
- Iterate until you see clean separation between intended positives and negatives
The test does not generate a response, mutate conversation state, or create a permanent record: it’s purely diagnostic.
For a Jev tag, “Test a message” sends the test message to Jev, the same way a live message is sent. It is not billed. If Jev is unavailable, the test shows an error. It does not fall back to the embedding classifier. See Jev privacy and data processing for what is sent.
Jev privacy and data processing
This section is the official description of how Chipp handles message text for tags that use the Jev classifier. New tags use Jev. Older tags use the embedding classifier and never call Jev (see the note at the end of this section).
Chipp checked this section against its source code and against the public documents of each vendor on 2026-10-26. Some facts could not be confirmed from a public source. Those facts are marked pending confirmation, and each has a named owner. This section never fills a gap with a guess.
Three points need a decision from you before you use tags with end users under 18: (1) Chipp has not confirmed that its data processing terms cover the Jev path, (2) OpenRouter and TypeSafe are not on Chipp’s published subprocessor list, and (3) no BAA is confirmed for either vendor. See “Minors’ data” below.
Review owners
Every statement below names the person or role who reviews it. No CODEOWNERS file exists for these documents. The owners below are proposed, and the legal owner is not yet named.
| Owner | Who | Status |
|---|---|---|
| Doc owner | Hunter Hodnett, Co-CEO at Chipp | Proposed |
| Legal owner | Chipp legal and compliance owner (role only, person not yet named, contact info@chipp.ai) | Pending naming |
| Infra owner | Chipp platform infrastructure owner who holds the OpenRouter admin login (proposed: Hunter Hodnett), with the Chipp security lead as reviewer | Proposed |
| Vendor owner | Chipp vendor-management owner (role only, person not yet named) | Pending naming |
Vendors can change their terms at any time. The proposed periodic reviewer is the Chipp security lead, every quarter.
The processing chain
End user -> Chipp -> OpenRouter -> TypeSafe (Jev model)| Party | Role in this flow | Source |
|---|---|---|
| Chipp | Stores the conversation. After (or, for some tags, before) the AI reply, it sends the one message plus your tag definitions to OpenRouter. It uses a Chipp-managed OpenRouter credential. You never see or set this credential. | Chipp code check, 2026-10-26. |
| OpenRouter | API router. It receives the request at its /api/alpha/decisions endpoint and sends it to the provider endpoint for the model typesafe/jev-1.13. OpenRouter’s own DPA names its customer as controller and OpenRouter as processor. | OpenRouter DPA, section 2.1 (https://openrouter.ai/data-processing-agreement, last updated 2026-08-26), retrieved 2026-10-26. Owner: Doc owner. |
| TypeSafe | Maker of the Jev model (Chipp calls it TypeSafe System One). OpenRouter lists typesafe/jev-1.13 under the TypeSafe author page. TypeSafe’s own DPA names its own customer as controller and TypeSafe as processor. | https://openrouter.ai/typesafe, retrieved 2026-10-26. TypeSafe DPA, section 1.1 (https://www.typesafe.ai/legal/data-processing, last updated 2026-04-24), retrieved 2026-10-26. Owner: Doc owner. |
Chipp does not call TypeSafe’s own API. The call goes through OpenRouter only.
Three points are pending confirmation:
- The legal role (controller or processor) of Chipp, of you as the builder, and of each vendor for message text sent through tags. Owner: Legal owner.
- Which exact provider endpoint behind OpenRouter serves
typesafe/jev-1.13. The OpenRouter model page for this model returned an error on 2026-10-26, so the endpoint’s data policy and region could not be read. Owner: Vendor owner (ask OpenRouter support and TypeSafe at privacy@typesafe.ai). - Whether any contract exists between OpenRouter and TypeSafe that covers Chipp’s data. No fetched source says. Owner: Legal owner.
What data is sent
For each classification, Chipp sends one request to OpenRouter. The request holds:
| Sent | Detail |
|---|---|
| The message | The text of the one message being classified, as one string. Chipp does not cut the message to a maximum length in the tag code. |
| Your tag definitions | For every enabled Jev tag in the app: the tag name and the tag description. |
| Your examples | For each tag, up to 20 positive and up to 20 negative example phrases. Each phrase is cut to 300 characters. Blank phrases are skipped. |
| Model name | typesafe/jev-1.13 |
| Credential and fixed headers | Chipp’s OpenRouter credential, and the fixed headers HTTP-Referer: https://chipp.ai and X-Title: Chipp. |
Chipp does not send: earlier messages from the chat history, the assistant’s reply, your system prompt, the session ID, the app ID, or the organization ID. Chipp adds no name, email or ID of its own to the request. The one string can still contain such data in two ways: the end user can type it in the message, and the Slack channel adds some data to the stored message (see “Slack thread replies” below).
Only the current message is sent. Jev gets no conversation context. It does not see the history of the chat. Any change to what Jev receives will be made in a separate change, and this section will be updated when it ships.
Know three details about “the current message”:
- It is the message as Chipp stores it for that turn. Some channels add content to the stored message (see “Slack thread replies” and “Channels that send more than the typed text” below). A voice message is sent as its transcript.
- If an app has more than 20 enabled Jev tags, Chipp splits the tags into groups of 20. Each group is a separate request, and each request holds the message. The requests run in parallel.
- A tag with a static reply and real-time detection runs before the AI reply. Chipp then also classifies the same message after the reply, as a separate request. The second request is not a retry. It exists because the after-reply step checks all tags.
Slack thread replies
Jev still gets one stored message and no chat history. On Slack, the stored message for a thread reply is longer than the typed text, because Chipp builds it before it stores it. The tag check reads that stored text (src/services/slack-chat.service.ts:1364-1395, 2417-2419). Each of these items can be in the one string:
| Item in the string | When | Code |
|---|---|---|
The author name prefix: the Slack real name, else the display name, else the Slack user ID in the form <@U...>. It is added as Name: text. | The message is a reply in a thread. It is not added for the thread’s first message. | src/services/slack-chat.service.ts:1331-1337; label rule in src/services/slack-thread-context.ts:309-326 |
Other people’s thread messages: each line has the author label of that person (the real name, else the Slack ID, else a bot or user name), the message text, and [attached: file names]. Mentions inside the text are rewritten to names. | Chipp adds the messages of the thread that the bot has not yet received. For a new session, or a session with no stored messages, this is the whole thread. For a later reply, it is the messages since the last turn. | src/services/slack-thread-context.ts:335-385; added at src/services/slack-chat.service.ts:1363-1365 |
| The text of files attached in the thread messages | When Chipp can read the files. | src/services/slack-thread-context.ts:373-383 |
| A file block: for each file of the thread messages and of the new message, the file name, the file ID, the MIME type and the size. For an image, it also holds a signed download URL. | The new message or the thread messages carry files. | src/services/slack-chat.service.ts:1347-1350; src/api/routes/consumer/chat/shared-chat-pipeline.ts:2327-2372 |
| The inline text of attachments, and notes about attachments that Chipp skipped | The new message carries attachments. | src/services/slack-chat.service.ts:1352-1357 |
So on a Slack thread reply, Chipp can send the name of the author, the names or Slack IDs of other participants, their messages, file names, file IDs and signed image URLs to OpenRouter and TypeSafe. The tag check on Slack is skipped in zero data retention mode (src/services/slack-chat.service.ts:2417). The sentence “Only the current message is sent” is correct for Slack in this sense: Jev gets one stored message. That stored message holds thread content. Whether Chipp should send only the typed text on Slack is pending confirmation. Owner: Doc owner (see Open items).
Channels that send only the single message string
For these channels, the string that Chipp stores as the user message is the string that Chipp sends to the tag check, with no added block (checked 2026-10-26):
- Discord (
src/services/discord-chat.service.ts:435,1017-1018) - Microsoft Teams (
src/services/teams-chat.service.ts:520,1151-1152) - Telegram (
src/services/telegram-chat.service.ts:564,1110-1111) - SMS (
src/services/sms-chat.service.ts:586,1163-1164) - iMessage (
src/services/imessage-chat.service.ts:544,1068-1069) - Linq (
src/services/linq-chat.service.ts:526,1071-1072)
Channels that send more than the typed text
- Slack: see “Slack thread replies” above.
- Email: the string holds the message plus the file block and the inline text of attachments (
src/services/email-chat.service.ts:1709-1728,2569-2570). - GitHub: for the first message of a session, Chipp adds the details of the issue or pull request before the message (
src/services/github-chat.service.ts:640-659,1257-1258). - WhatsApp: a media message is sent as the text that Chipp makes from the media, for example a transcript, or as an error text (
src/services/whatsapp-chat.service.ts:1005-1025,1477,2336-2337).
For these channels, the string can hold data that the end user did not type. Whether Chipp should send only the typed text is pending confirmation. Owner: Doc owner (see Open items).
When Chipp sends nothing to Jev:
- The app has no enabled tag. Chipp makes no request.
- The message is empty or only spaces.
- The after-reply step is skipped when the app uses zero data retention, encrypted storage, or on-device privacy. Channel paths such as Slack also skip it in zero data retention mode.
Current limit: the before-reply check for real-time static-reply tags does not look at zero data retention, encrypted storage or on-device privacy. In the current code, such a tag still sends the message to Jev in those modes. Do not rely on those modes alone to keep a message away from Jev. Owner: Doc owner to confirm that this is the intended behavior.
Source for this subsection: Chipp code check, 2026-10-26. This subsection covers what Chipp does. It makes no claim about vendor retention, region or contracts.
Retention and logging
| Party | Statement | Status | Source and retrieval date | Review owner |
|---|---|---|---|---|
| Chipp logs | Chipp’s application logs for Jev calls hold only identifiers, scores, timings, token counts, the error class and a masked error code. They never hold message text, the credential, or the request or response body. | Confirmed (what Chipp logs) | Chipp code check, 2026-10-26 | Doc owner |
| Chipp log retention period | How long Chipp keeps these log lines. | Pending confirmation | No published source | Doc owner |
| Chipp stored data | When a tag matches, Chipp stores one tag-instance row: message ID, tag ID, score, threshold, the model name and a flag for replaced text. The message text itself is stored as part of the conversation, under your app’s normal data settings. Chipp also stores one usage row per call (token count, model, number of tags), with no message text. | Confirmed (what is stored) | Chipp code check, 2026-10-26 | Doc owner |
| Chipp retention period for tag classification data | How long Chipp keeps the tag-instance and usage rows. | Pending confirmation | No published source | Doc owner |
| OpenRouter, training | OpenRouter does not use your Inputs or Outputs for model training. OpenRouter does not control how model providers handle Inputs and Outputs. | Confirmed (vendor statement) | OpenRouter Privacy Policy, last updated 2026-08-31 (https://openrouter.ai/privacy), retrieved 2026-10-26 | Doc owner |
| OpenRouter, storage of prompts | OpenRouter does not store prompts or responses unless the account opts in to “Private Input & Output Logging” or “OpenRouter Use of Inputs/Outputs”. Both are off by default. OpenRouter stores metadata (token counts, latency) without prompt content. | Confirmed (vendor default) | https://openrouter.ai/docs/guides/privacy/data-collection, retrieved 2026-10-26 | Doc owner |
| OpenRouter, deletion | If the account has not opted in to logging, OpenRouter deletes Inputs and Outputs “promptly following generation of the relevant Output”. Exceptions: where the law requires it, and to address malicious use. Automated risk classification may run before deletion. | Confirmed (vendor DPA) | OpenRouter DPA, section 2.4 (last updated 2026-08-26), retrieved 2026-10-26 | Doc owner |
| OpenRouter, if logging is on | OpenRouter keeps logged data for at least 3 months, and may keep it longer unless you ask for deletion. Opt-in prompt logging also gives OpenRouter a perpetual license to the logged content, including to license or sell it in anonymized form. | Confirmed (vendor terms) | https://openrouter.ai/docs/guides/features/input-output-logging, and OpenRouter Terms section 6.2 (https://openrouter.ai/terms), retrieved 2026-10-26 | Doc owner |
| OpenRouter, license to anonymized Inputs | Whether or not prompt logging is on, OpenRouter’s Terms section 6.5 give OpenRouter a “worldwide, perpetual, irrevocable, non-exclusive, royalty-free, fully paid right and license (with the right to sublicense) to use, host, reproduce, and prepare derivative works of, your Inputs in anonymized form, solely for tracking and sharing user metrics on the Site, such as for example, on our Rankings Page”. The same section says that “Unless explicitly opted in to prompt logging, we do not store your Inputs after categorizing them and do not associate the categorized Inputs with any specific user or organizational accounts.” Message text sent through tags is an Input. Whether Chipp’s account accepted these Terms in a way that covers this use is pending confirmation. | Confirmed (vendor terms); Chipp’s acceptance pending confirmation | OpenRouter Terms of Service, section 6.5, last updated 2026-08-31 (https://openrouter.ai/terms), retrieved 2026-10-26 | Legal owner |
| OpenRouter, Chipp’s account settings | Whether Chipp’s managed account has Input & Output Logging on, “OpenRouter Use of Inputs/Outputs” on, training opt-out set, a zero-data-retention policy set, or a regional endpoint in use. The vendor defaults above apply only if Chipp did not change them. | Pending confirmation | No dashboard view is available to Chipp’s documentation process | Infra owner |
| OpenRouter, model providers | Each AI provider on OpenRouter has its own logging and retention policy. OpenRouter does not change its routing rules based on provider retention. OpenRouter’s privacy policy says model providers may keep and use Inputs and Outputs under their own terms. For an unclear provider policy, OpenRouter assumes the endpoint keeps and trains on data. | Confirmed (vendor statement) | https://openrouter.ai/docs/guides/privacy/logging and OpenRouter Privacy Policy section 3, retrieved 2026-10-26 | Doc owner |
| TypeSafe, training | TypeSafe says it will not train or fine-tune models on your prompts or other Input, and will not disclose Input to a third party other than its service providers. Its models page says Jev is not trained on customer requests or responses. | Confirmed (vendor statement) | TypeSafe Privacy Policy, last updated 2025-11-19 (https://www.typesafe.ai/legal/privacy-policy), and https://docs.typesafe.ai/models.md, retrieved 2026-10-26 | Doc owner |
| TypeSafe, retention | TypeSafe publishes no fixed number of days. Its privacy policy says “We retain personal data about you for as long as reasonably necessary to provide you with the Services, or otherwise in support of our business or commercial purposes.” Chipp does not know whether TypeSafe treats message text from calls through OpenRouter as personal data under that sentence. Its MCA (customer agreement) lets it keep “Telemetry” without a time limit (technical logs, hashes, summary statistics and classifications). Zero data retention is “available for enterprise customers”. It is not stated as the default. | Confirmed (vendor statement, no fixed period) | TypeSafe Privacy Policy; TypeSafe MCA sections 4.1(c) and 4.3, last updated 2026-09-23 (https://www.typesafe.ai/legal/mca); https://www.typesafe.ai/enterprise, retrieved 2026-10-26 | Doc owner |
| TypeSafe, retention for calls through OpenRouter | Whether TypeSafe keeps data from calls that arrive through OpenRouter, for how long, and whether the zero-data-retention option applies to them. TypeSafe’s terms cover its own direct customers. | Pending confirmation | No fetched source says | Vendor owner |
Processing and storage region
| Party | Statement | Status | Source and retrieval date | Review owner |
|---|---|---|---|---|
| Chipp | Chipp’s Trust Center lists Google Cloud Platform (Iowa) as a subprocessor. | Confirmed (published list) | https://trust.chipp.ai/subprocessors, retrieved 2026-10-26 | Doc owner |
| OpenRouter, default | OpenRouter’s DPA lists “Google Cloud Platform hosting in US regions; data at rest is region-restricted”. Its privacy policy says data may be transferred to servers in the US, or to other countries outside the EEA and the UK. | Confirmed (vendor statement) | OpenRouter DPA, Schedule 2, and OpenRouter Privacy Policy section 9, retrieved 2026-10-26 | Doc owner |
| OpenRouter, EU-only processing | EU-only processing applies only where the customer elected it in an order form or other written agreement (DPA Exhibit A). Regional endpoints (eu.openrouter.ai, us.openrouter.ai) are an OpenRouter paid-plan feature (its own Business and Enterprise tiers). Chipp’s code calls the global endpoint openrouter.ai, so Chipp does not use a regional endpoint. Whether Chipp elected EU-only processing is not shown. | Confirmed (vendor terms); Chipp election pending confirmation | https://openrouter.ai/docs/guides/features/in-region-routing, and OpenRouter DPA Exhibit A, retrieved 2026-10-26. Chipp code check, 2026-10-26 | Legal owner |
| TypeSafe | TypeSafe’s privacy policy says “The Services are hosted in the United States”. The enterprise page has an FAQ item “Where is our data processed?” but its answer could not be read. | Confirmed (vendor statement); enterprise FAQ pending confirmation | https://www.typesafe.ai/legal/privacy-policy, and https://www.typesafe.ai/enterprise, retrieved 2026-10-26 | Vendor owner |
| Provider endpoint behind OpenRouter | The region of the endpoint that serves typesafe/jev-1.13 through OpenRouter. | Pending confirmation | OpenRouter model page returned an error on 2026-10-26 | Vendor owner |
Subprocessors
| Item | Statement | Status | Source and retrieval date | Review owner |
|---|---|---|---|---|
| Chipp’s subprocessor list | The list has six entries: Google Cloud Platform (Iowa), GitHub, Google Workspace, Linear, Slack and Vanta. OpenRouter and TypeSafe are not on this list. No AI model provider is on it. | Confirmed (published list). The page is rendered in the browser and can change, so Chipp re-checks it before each edit of this section. | https://trust.chipp.ai/subprocessors, retrieved 2026-10-26 | Doc owner |
| Chipp’s privacy policy | The policy (last updated 2026-10-05) names OpenRouter only as a route to model makers. It does not name TypeSafe or Jev. It says only that providers keep data as their terms allow. | Confirmed | https://chipp.ai/privacy, retrieved 2026-10-26 | Doc owner |
| Whether to add OpenRouter and TypeSafe to Chipp’s list | Whether Chipp must list them as subprocessors for message text. | Pending confirmation | No published source | Legal owner |
| OpenRouter’s subprocessors | OpenRouter’s DPA (section 5.2) says its list is in Schedule 3. The list itself could not be read. OpenRouter gives notice of new subprocessors by email subscription, but not for AI model providers. A customer may set its account to exclude certain AI model providers. | Confirmed (terms); list pending confirmation | OpenRouter DPA section 5.2 and Schedule 3, https://trust.openrouter.ai/, retrieved 2026-10-26 | Legal owner |
| TypeSafe’s subprocessors | TypeSafe’s DPA (section 3.1) gives general authorization for the subprocessors listed at its Trust Center, with advance notice and a 15-day objection period for new ones. The list page showed no content when fetched. | Confirmed (terms); list pending confirmation | TypeSafe DPA sections 3.1 and 3.2, https://trust.typesafe.ai/subprocessors, retrieved 2026-10-26 | Vendor owner |
| Embedding fallback | When Jev fails and a tag has stored examples, Chipp can send the message to its embedding provider (see “Timeout and fallback”). That provider’s retention, region and contract terms are not covered here. | Pending confirmation | Chipp code check, 2026-10-26 | Legal owner |
DPA and BAA coverage
| Item | Statement | Status | Source and retrieval date | Review owner |
|---|---|---|---|---|
| Chipp DPA | Chipp does not publish a standalone DPA. The page https://chipp.ai/dpa returns “not found”. Chipp’s Terms (section 4, updated 2026-10-09) say to request a DPA at info@chipp.ai. The Terms do not say that a DPA covers Jev. | Confirmed (no published DPA) | https://chipp.ai/dpa and https://chipp.ai/terms, retrieved 2026-10-26 | Legal owner |
| Does Chipp’s DPA cover Jev, OpenRouter or TypeSafe? | Do not assume that it does. No DPA text is available to check. | Pending confirmation | No published source | Legal owner |
| OpenRouter DPA | OpenRouter’s Terms (section 10.2) incorporate its DPA by reference for organizations and for commercial use. The DPA names the customer as controller and OpenRouter as processor. It includes EU Standard Contractual Clauses (Module 2), the UK Addendum, and a 72-hour incident notice. The DPA says OpenRouter does not have to process Sensitive Data unless it says so, and Schedule 1 says no Sensitive Data is intended. The customer must review the model providers’ terms and set up its account. | Confirmed (vendor terms) | OpenRouter Terms section 10.2; OpenRouter DPA sections 2.1, 2.2, 2.6, 7, 13 and Schedule 1 (last updated 2026-08-26), retrieved 2026-10-26 | Doc owner |
| Does Chipp have an accepted OpenRouter DPA or signed order form? | Not shown by any source. | Pending confirmation | No published source | Legal owner |
| TypeSafe DPA | TypeSafe has a DPA. It is part of the TypeSafe MCA (section 4.4). It binds TypeSafe’s own customer. It includes the same SCC Module 2 and UK Addendum, and a 72-hour incident notice. Chipp reaches TypeSafe through OpenRouter. No fetched source says whether a TypeSafe DPA reaches Chipp, or whether OpenRouter has one with TypeSafe. | Confirmed (vendor terms); reach pending confirmation | TypeSafe DPA sections 1.1, 5.2, 6.2 and 6.3, and MCA section 4.4, retrieved 2026-10-26 | Legal owner |
| BAA | No BAA is confirmed for OpenRouter or for TypeSafe on this path. Chipp’s marketing says it has a BAA with “Google, Anthropic, and other AI providers”, and does not name OpenRouter or TypeSafe. Chipp’s internal BAA coverage check of 2026-07-30 found no BAA that covers OpenRouter-routed traffic and says Chipp legal must confirm. No OpenRouter page names a BAA. The TypeSafe enterprise page lists a BAA question, but its answer could not be read. Do not send protected health information through message tags. | Pending confirmation | Chipp Terms section 4; Chipp internal HIPAA BAA model coverage verification, 2026-07-30; OpenRouter privacy, terms and DPA pages; https://www.typesafe.ai/enterprise; all retrieved 2026-10-26 | Legal owner |
Minors’ data
What the sources say:
| Source | Statement | Retrieved |
|---|---|---|
| Chipp Privacy Policy (https://chipp.ai/privacy) | The platform is not intended for children under 18. Chipp does not knowingly collect data from children under 13. | 2026-10-26 |
| Chipp Terms, section 4 (https://chipp.ai/terms) | Children’s data needs a matching plan and signed agreements. | 2026-10-26 |
| TypeSafe Privacy Policy, “Children’s Privacy” | TypeSafe does not knowingly collect, keep or use personal data from children under 18, and no part of its Services is directed to children. | 2026-10-26 |
| OpenRouter Privacy Policy section 8 and Terms section 2 | OpenRouter’s site and service are for users 18 or older. No sentence addresses the data of end-user minors that pass through an API customer. | 2026-10-26 |
| OpenRouter DPA and TypeSafe DPA | Neither DPA covers children’s data. The TypeSafe DPA lists sensitive data as “N/A”. | 2026-10-26 |
No source says that text from end users under 18 may, or may not, be processed through the Chipp, OpenRouter and TypeSafe path. Whether Chipp needs a DPA or other agreement for this use is pending confirmation. Owner: Legal owner. The review owner for this subsection is the Legal owner, with the Doc owner as second reviewer.
Recommendations if your app serves users under 18. These are practice recommendations from Chipp’s engineering team. They are not legal advice.
- Get written confirmation first. Email info@chipp.ai before you enable tags on an app that under-18 users can reach. Ask whether the data processing terms cover the Jev path for children’s data. Until Chipp confirms in writing, treat the answer as “not confirmed”.
- If you cannot get confirmation, turn the tags off. Disable every tag in that app. When an app has no enabled tag, Chipp sends nothing to Jev. You cannot switch a tag to a different engine yourself.
- Keep personal data out of tag definitions. The tag name, description and example phrases go to OpenRouter and TypeSafe with every message. Do not put names, schools or other personal data in them.
- Tell students what to avoid. Add a short notice at the start of the chat that asks users not to enter their name, address, school, health details or other personal data.
- Do not rely on zero data retention alone. In the current code, a real-time static-reply tag still sends the message in that mode (see “What data is sent”).
- Check your own duties. Your school contracts and your local child-privacy laws can add rules. Ask your own legal adviser or your school’s data-protection officer. The vendor sources above do not answer this.
Timeout and fallback
Chipp waits 2 seconds for each Jev request. After that, it cancels the request and treats Jev as unavailable. Jev usually answers in 70 to 500 milliseconds. The 2-second limit is the worst case for the Jev call alone. A local embedding fallback can add more time before the AI reply for some tags (see the list below).
Chipp does not retry a failed request. A failure here means a timeout, a rate limit (HTTP 429), an HTTP error, a network error, a response that is not a valid answer, or a missing credential. Chipp sends the message once per request. The message is not queued for a later try.
What each tag gets after a failure:
| Situation | Tag result | What the end user sees |
|---|---|---|
| The tag has stored example embeddings (an older tag, or a copied tag, or a tag whose examples were embedded) and the fallback works | The embedding classifier decides for that tag. The result can be a match. A match runs the tag actions in the same way as a Jev match, including the static reply, the conversation freeze, notifications and webhooks. For the after-reply step, Chipp embeds the message with its embedding provider. For the before-reply step, Chipp uses an embedding model that runs inside Chipp’s own servers, with no external call. | The tag works as an embedding tag would. For a before-reply static-reply tag, a match shows the static reply instead of the AI reply. |
| The tag has stored example embeddings, but the fallback also fails (for example, the in-process embedding model is not ready, or it exceeds its 3-second limit) | No result for that tag. | Nothing changes. |
| The tag has no stored embeddings (the normal case for a new Jev tag) | No result for that tag. The message is dropped for that tag. | Nothing changes. |
| The message is empty or only spaces | Chipp does not send a request. No result. | Nothing changes. |
A tag with no result records no tag instance. It sends no notification or webhook, shows no static reply, and does not freeze the conversation. The conversation goes on as normal. The message is not tagged again later.
- Before the AI reply (real-time static-reply tags): Chipp waits up to 2 seconds for Jev. If Jev fails and the tag has stored example embeddings, Chipp then runs the local embedding fallback. It starts only after the Jev call has failed, and it has its own limit of 3 seconds. So the worst case before the reply is about 5 seconds (2 seconds for Jev, then 3 seconds for the fallback). If the fallback matches, the result can trigger the static reply (or the conversation freeze) in place of the AI reply. If Jev fails and the tag has no stored embeddings, or the fallback also fails, the AI answers as normal. Code: 2-second limit set at
src/services/tag-classifier/jev-config.ts:33and applied atsrc/services/tag-classifier/jev-client.ts:384; fallback insrc/services/tag-detection.service.ts:465-513,981-1020; 3-second limit atsrc/services/tag-detection.service.ts:863; static reply or freeze from a match atsrc/services/tag-detection.service.ts:1029-1046. - After the AI reply (all other tags): the check never delays the reply. The fallback for the after-reply step uses Chipp’s embedding provider (an external call) and has no 3-second limit in the tag code.
In “Test a message” in the tag editor, a failed Jev call shows an error. It does not use the embedding fallback.
Source for this subsection: Chipp code check, 2026-10-26. Review owner: Doc owner.
Older tags (embedding classifier)
Tags created before Jev keep the embedding classifier. They never call Jev, OpenRouter or TypeSafe for classification. Chipp turns the message into an embedding with its embedding provider, or with a model that runs inside Chipp’s own servers for real-time tags. The retention, region and contract terms of that embedding provider are pending confirmation. Owner: Legal owner.
Open items
Chipp lists every pending item here so a person can close it. Each item has an owner. Every place in this section that says “pending confirmation” matches one item below. The roles are named in “Review owners”.
- Chipp’s OpenRouter account settings: prompt logging, “OpenRouter Use of Inputs/Outputs”, training opt-out, zero data retention policy, regional endpoint. Owner: Infra owner.
- Whether Chipp has an accepted OpenRouter DPA or signed order form, and whether it elected EU-only processing. Owner: Legal owner.
- The data policy, retention and region of the provider endpoint that serves
typesafe/jev-1.13through OpenRouter, and whether it is eligible for zero data retention. Owner: Vendor owner. - Whether Chipp’s DPA covers Jev, OpenRouter and TypeSafe, and whether Chipp must publish a DPA. Owner: Legal owner.
- Whether OpenRouter and TypeSafe must be added to Chipp’s subprocessor list. Owner: Legal owner.
- OpenRouter’s subprocessor list (Schedule 3). Owner: Legal owner. TypeSafe’s subprocessor list. Owner: Vendor owner.
- BAA coverage for OpenRouter and TypeSafe. Owner: Legal owner.
- The use of text from end users under 18: whether a DPA or other agreement is required. Owner: Legal owner.
- Whether TypeSafe keeps data from calls through OpenRouter and for how long, whether its zero-data-retention option applies to them, whether TypeSafe treats that message text as personal data under its retention sentence, and the answers on its enterprise page for region and zero data retention. Owner: Vendor owner.
- Retention periods for Chipp’s own logs and for tag-instance and usage rows. Owner: Doc owner.
- Retention, region and contract terms of the embedding provider that Chipp uses in the fallback path and for older tags. Owner: Legal owner.
- Whether the before-reply real-time tag check should skip zero data retention, encrypted and on-device privacy modes. Owner: Doc owner.
- Naming the Legal owner, the Infra owner and the Vendor owner as people. Owner: Doc owner.
- The legal role (controller or processor) of Chipp, of the builder, and of each vendor for message text sent through tags. Owner: Legal owner.
- Whether any contract exists between OpenRouter and TypeSafe that covers Chipp’s data, and whether TypeSafe’s DPA reaches Chipp. Owner: Legal owner.
- Whether Chipp’s account accepted OpenRouter Terms section 6.5 (the perpetual license to use Inputs in anonymized form) in a way that covers message text from tags. Owner: Legal owner.
- Whether Slack (thread author names, other participants’ messages, file names, file IDs and signed image URLs) and the other channels that add content to the stored message (email, GitHub, WhatsApp) should send only the typed text to Jev. Owner: Doc owner.
Troubleshooting
Tags Aren’t Detecting Anything
- Move the sensitivity slider toward Sensitive
- Make the description more specific, or add more varied example phrases
- Check that the tag is enabled
Too Many False Positives
- Move the sensitivity slider toward Strict
- Make example phrases more specific
- Remove overly generic examples
Tags Detecting the Wrong Things
- Review your example phrases for unintended patterns
- Use negative examples: See the “Negative Examples” section above. This is especially effective for hard compliance boundaries where legitimate messages are semantically similar to prohibited ones.
- Test before deploying: Use “Test a message” (see “Calibrating Tags” above) to validate your positive/negative/threshold combination against real prompts before enabling the tag live.
- Move the sensitivity slider toward Strict if you’re getting false positives on completely unrelated topics
- Consider splitting into more specific tags if you have multiple distinct intents
Next Steps
Now that you understand message tagging, try setting up your first tag:
- Think about what user messages you most want to detect
- Create a tag with a precise description (and, optionally, 3-5 good example phrases)
- Start at the default 50% sensitivity
- Monitor your chat history for a few days
- Tune based on what you observe
Tags become more valuable over time as you refine them based on real user interactions. Start simple, iterate often, and you’ll build a powerful automation layer for your AI app.
Using with MCP
You can manage tags programmatically using the Chipp MCP Server, including AI-powered utterance generation.
Available Tools
| Tool | Description |
|---|---|
list_tags | List all tags for an app, with per-origin example counts (example_counts) |
create_tag | Create a new tag with a description, examples, and actions |
update_tag | Update tag name, description, examples, or actions |
list_tag_examples | List the full set of examples a tag classifies with (prefab and custom), or export it as CSV |
set_tag_examples | Replace a tag’s custom example phrases |
add_tag_examples | Append custom example phrases to a tag |
delete_tag | Remove a tag |
list_tag_instances | View messages that matched a tag |
chat_with_app | Send a message to the app as a test. The message is classified for tags |
log_chat_message | Record a conversation from another system. The first user message is classified for tags |
remove_tag_instance | Remove a false positive match |
generate_utterances | AI-generate training phrases for a tag (up to 100 per call) |
Example Prompts
"Create a tag called 'pricing_intent' for my sales bot"
"Generate 50 utterances for detecting refund requests"
"Show messages that matched the 'human_needed' tag"
"Remove the false positive from tag instance xyz"Workflow: AI-Powered Tag Training
You: Create a tag for detecting pricing questions in my B2B sales bot
AI: [Calls create_tag]
Created tag "pricing_intent". Would you like me to generate
training utterances?
You: Yes, generate 100 varied examples for B2B software pricing
AI: [Calls generate_utterances with count=100 and a tag_description
about B2B software pricing]
Generated 100 utterances including:
- "How much does your enterprise plan cost?"
- "What's the pricing for 100 users?"
- "Do you offer volume discounts?"
- "Is there a free trial available?"
...
AI: [Calls add_tag_examples]
Saved to tag "pricing_intent". The tag is now active.MCP server access requires a Builder plan or higher. See the MCP Setup Guide to get started.