Anatomy of a tag
| Field | Description |
|---|---|
slug | Stable URL-safe identifier (e.g., needs-review, tax-deductible). Used in rule actions, MCP tool calls, and the ?tags= query filter. |
display_name | Human-readable label shown in the dashboard. |
description | Optional short explanation of what the tag means. |
color | Hex color for the dashboard pill. |
lifecycle | Either persistent or ephemeral — see below. |
short_id alongside its internal UUID, same as every other entity in Breadbox.
Persistent vs. ephemeral
Lifecycle controls whether the tag is treated as a permanent label or a temporary flag.persistent(the default) — the tag sticks to the transaction until you remove it. Good for durable labels liketax-deductible,reimbursable,shared-with-partner.ephemeral— the tag is expected to come off. Every removal requires a short note, which is recorded as an annotation on the transaction’s activity timeline. Good for workflow flags likeneeds-review,disputed,pending-refund— where the act of resolving the flag is itself information worth keeping.
The note requirement is enforced at the service layer. If an agent tries to remove an ephemeral tag without supplying a rationale, the call is rejected before the tag comes off.
Seeded tags
Breadbox ships with one tag out of the box:| Slug | Lifecycle | What it’s for |
|---|---|---|
needs-review | ephemeral | Applied to every newly-synced transaction by a seeded on_create rule. Removing it closes a review. See the review workflow. |
How tags get applied
A tag reaches a transaction one of four ways — and the activity timeline records which one:Manual (user)
From the transaction detail view in the dashboard, add or remove a tag directly. Recorded as
added_by_type = user.Agent (MCP)
An AI agent connected over MCP calls
update_transactions with tags_to_add or tags_to_remove (each entry can include an inline note). Recorded as added_by_type = agent.Rule action
A transaction rule with
add_tag or remove_tag in its actions fires during sync (trigger on_create) or retroactively (trigger on_apply). Recorded as added_by_type = rule, with the rule’s ID on the annotation so you can trace why the tag landed.Querying by tag
The?tags= query parameter and the tags= filter on MCP tools both accept a list of slugs. The default behavior is all-of: a transaction must carry every listed tag.
any_tag= instead:
query_transactions tool accepts the same parameters.
Tags in rules
Tags are both a condition and an action in the rule DSL:- As a condition, rules can match on
tags contains "needs-review"ortags not_contains "disputed"to gate which transactions they affect. - As an action, rules can
add_tagorremove_tagto manage tag state automatically. A rule that adds a tag can be scheduled (triggeron_createduring sync) or run retroactively against historical data.
needs-review: define a tag, then write rules that apply or remove it under the conditions you care about.
Example: a disputed-charges workflow
Suppose you want a dedicated queue for charges you intend to contest with your bank. The ingredients:Create a `disputed` tag (ephemeral)
From Tags in the dashboard, add a new tag with slug
disputed, lifecycle ephemeral, and a description like “Charge we’re contesting — remove with outcome note when resolved.” Ephemeral means the note you leave when you take it off becomes part of the transaction’s history.Apply it when you see a bad charge
Tag the transaction manually from the dashboard, or have an agent tag it by name pattern via
update_transactions. No rule necessary — you apply it reactively.Use `?tags=disputed` as your queue
Same pattern as review: filter the transactions list to
tags=disputed and the page becomes your dispute-tracking view. No new UI needed.