Skip to main content
How-To Guides Last updated: 2 October 2026

KQL Search Reference for Outlook Assistant

Use Microsoft Graph $search expressions (KQL-style syntax) to write precise search queries for emails by date, sender, subject, and message properties.

Nathan Schram
By Founder, Little Bear Apps

The searchExpression parameter lets you pass a raw Microsoft Graph $search expression — KQL-style syntax, but not full KQL — for precise searches when the standard filter parameters aren’t enough.

Using searchExpression in Outlook Assistant

Pass a raw Graph $search expression through the searchExpression parameter (formerly kqlQuery, still accepted as a deprecated alias):

tool: search-emails
params:
  searchExpression: "from:sarah@company.com AND subject:quarterly"

When you use searchExpression, it bypasses other search parameters (from, subject, etc.) and sends the raw expression directly to the Graph API.

Search across all fields:

searchExpression: "budget approval"

Search by Field

FieldExample
Senderfrom:sarah@company.com
Recipientto:team@company.com
Subjectsubject:quarterly report
Bodybody:action required
CCcc:manager@company.com

Personal accounts (issue #217): Personal Outlook.com accounts reject field-scoped $search outright — Graph answers subject:"invoice" or from:github.com with a syntax error or an empty set even when the mail is plainly there. Since v3.10.0, expressions built purely from from:, to: and subject: terms are translated into the closest equivalent OData filters and retried down the normal fallback ladder, reported as strategy raw-kql-translated with the rewrite recorded in _meta.searchMetadata.kqlTranslatedTo. The translation is close rather than identical — a KQL subject: term becomes a substring match. body:, cc:, received:, hasAttachment: and isRead: are not translated. See Which expressions translate below.

Combine Conditions

These operators are a work/school account feature. On a personal Outlook.com account Graph rejects them and Outlook Assistant will not guess at a rewrite — use the structured filter parameters instead. See Which expressions translate.

AND — both must match

searchExpression: "from:sarah AND subject:quarterly"

OR — either must match

searchExpression: "from:sarah OR from:james"

NOT — exclude results

searchExpression: "subject:report NOT from:noreply@github.com"

Parentheses — group conditions

searchExpression: "(from:sarah OR from:james) AND subject:review"

Date Ranges

searchExpression: "received>=2026-01-01 AND received<=2026-01-31"
searchExpression: "sent>=2026-02-01"

Attachment and Flag Filters

searchExpression: "hasAttachment:true"
searchExpression: "isRead:false"

Common Patterns

GoalSearch Expression
Emails from a specific sender this yearfrom:boss@company.com AND received>=2026-01-01
Unread emails with attachmentsisRead:false AND hasAttachment:true
Emails about a project from anyonesubject:\"Project Alpha\" OR body:\"Project Alpha\"
Emails from a domainfrom:@company.com
Recent emails excluding newslettersreceived>=2026-02-01 NOT from:newsletter@

searchExpression vs Filter Parameters

ApproachPersonal AccountWork/School AccountWhen to use
Filter params (from, subject, etc.)Full supportFull supportRecommended default — reliable on all accounts
query paramLimited (auto-fallback)Full supportFree-text search; falls back to filters on personal accounts
searchExpression paramField-scoped from:/to:/subject: translated to filters and retried (v3.10.0); everything else terminates with an explicit no-resultsFull supportComplex queries: AND/OR/NOT, date ranges, multi-field (work accounts only)

On personal Outlook.com accounts, query and searchExpression use Microsoft’s $search API, which is not fully supported. query falls back through OData filters, boolean filters, and a client-side scan. searchExpression falls back only for the expressions it can reproduce exactly (from:, to:, subject: — see below); anything else deliberately terminates with an explicit “no results” rather than quietly running a broader search you didn’t ask for. Structured filter parameters (from, subject, to, receivedAfter, hasAttachments, unreadOnly) use OData $filter and work reliably on all account types — they remain the most direct route.

Whatever runs, _meta.searchMetadata tells you which strategy answered and droppedFilters lists any filter that could not be honoured. droppedFilters should always be empty; anything else means the result set is broader than your query (#229).

Unscoped expressions are a different search from query, not a synonym. searchExpression: "invoice" reaches Graph $search untouched, which matches the whole message including the body and orders results by relevance, not by date. query: "invoice" on a personal account becomes a subject substring match that never reads bodies. So the same term can legitimately produce two different result sets: searchExpression may return a message whose subject looks unrelated (the term is in its body), and query may miss a message that is obviously about the term (it isn’t in the subject). Neither is a dropped filter. Reach for query when your term is in a subject line, searchExpression when you need body content.

Which expressions translate on personal accounts

The translator is deliberately strict — it declines anything whose meaning it cannot reproduce exactly, because guessing would return mail you didn’t ask for.

ExpressionPersonal account behaviour
from:sarah@company.comTranslated → from filter
to:team@company.comTranslated → to filter
subject:"quarterly report"Translated → subject substring filter
from:sarah subject:reviewTranslated → both filters combined
budget approval (unscoped)Sent to $search unchanged — never affected by #217
from:sarah AND subject:reviewNot translated — boolean operators
(from:sarah OR from:james)Not translated — grouping
from:sar*Not translated — wildcards
body:urgent, cc:manager@x.comNot translated — field outside from/to/subject
received>=2026-01-01Not translated — use the receivedAfter parameter
from:a from:bNot translated — repeated field is ambiguous

For anything in the “not translated” rows on a personal account, use the structured filter parameters instead — they express the same intent through $filter and work everywhere.

Tips

  • Enclose multi-word phrases in escaped quotes: subject:\"Project Alpha\"
  • A searchExpression is sent exactly as you write it, so escape any " or \ inside your own phrase with a backslash, as Graph receives it: subject:"the \"big\" launch", "C:\\Reports" (since v3.12.1 query, search-people and export searchQuery text is escaped for you)
  • Graph $search matching is case-insensitive
  • Date format is YYYY-MM-DD
  • If a searchExpression returns no results, check _meta.searchMetadata.finalStrategy — then try the simpler query parameter or the structured filters, which are more forgiving
Was this helpful?

Related Articles