Contains Text
One clean boolean for 'is this phrase in there?'
- contains
Contains Text (StringContains) asks the most common question in text automation: is this substring inside this string? Yes or no, as a clean boolean you can route. Where Compare Text asks "is the whole thing X," and Match Text asks "does a pattern match," this one asks the dumb, everyday question - "does this prompt mention 'watermark'?" - and answers it without any regex.
That's its whole appeal: no pattern syntax, no escaping, no flags to reason about. You type the exact phrase and get a boolean. It's the natural building block for conditional workflows - check whether an LLM's output contains a JSON marker before parsing, detect whether a generated filename contains a variant tag, gate a cleanup step on whether a phrase showed up at all. And because it takes two plain strings, it's the node you can wire directly from other text nodes without a second thought.
How it works
Under the hood it's Python's substring membership test - substring in string - which is a literal substring search. Important distinction: "cat" matches "concatenate" (it's in there), so this is not word-boundary-aware, and it's not a pattern - a period in your substring matches a literal period. Inputs:
- string - the text to search in.
- substring - the text to look for.
- case_sensitive - defaults to true. Same default as Compare Text, opposite of the regex nodes. If "Dog" never matches when you're searching for "dog," this is why.
Output: a single BOOLEAN named contains. True if the substring appears anywhere, false otherwise.
A concrete pattern to steal: you're routing LLM output and the model sometimes returns a refusal instead of a prompt. Check Contains for "I can't" (or "sorry"), and when it returns true, reroute to a retry path instead of feeding the refusal into your CLIP Text Encode and generating nonsense. One boolean, one router, no regex - that's the entire job, done.
Common issues
The substring-means-anywhere behavior is the main surprise - searching for "an" matches virtually everything, and searching for a single letter will light up your routing in ways you didn't intend. If you need word-boundary or start/end anchoring, that's Compare Text (Starts With/Ends With) or a regex node's territory. Second: the case-sensitive default, especially if you've been using RegexMatch's case-insensitive default - two adjacent boolean nodes with different defaults is a genuine footgun. And empty substring is an edge: an empty substring technically "is in" every string, so if your substring comes from a possibly-empty upstream node, guard against it or every check returns true. For most "does it mention X" logic, though, this node is the one you'll keep reaching for.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| string | STRING | — | |
| substring | STRING | — | |
| case_sensitive | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| contains | BOOLEAN | — |