Skip to content

Collected Data Tools โ€‹

Single consolidated tool for viewing and analyzing data that your agents have automatically extracted from conversations.

Use cases:

  • View leads, feedback, or applications collected by agents
  • Monitor collection performance with dashboard statistics
  • Filter and search collected data by agent, template, date range

Recommended workflow: Use action="stats" first to see totals and trends, then action="list" for specific records, then action="get" to pull one record's full detail (incl. provenance and session excerpt).

Tip: for a full, filter-aware CSV download of collected data (all matching records, not a single page), use the REST endpoint GET /api/v1/entities/export instead of paging this tool's action="list".


gnosari_collected_data โ€‹

List or summarise data your agents have collected from conversations.

Annotations: readOnlyHint: true ยท destructiveHint: false ยท idempotentHint: true ยท openWorldHint: false

Parameters โ€‹

NameTypeRequiredDefaultDescription
actionstringNo"list"list to browse records, get to fetch one record's full detail (incl. provenance and session excerpt), stats for dashboard totals
agent_idintegerNo-Filter by a specific agent
entity_idintegerNo-Id of a single collected record to fetch. Required for action="get"
template_namestringNo-Filter by template name (e.g., "candidates", "leads"). Case-insensitive. list action only
daysintegerNo-Relative date filter in days (e.g., 1=today, 7=last week, 30=last month). For stats, omit for all-time (no date cutoff) -- this is the default. list is unaffected: omitted days there already means unfiltered
statusstringNo-Filter by data status: new, reviewed, actioned, archived. list action only
searchstringNo-Search within collected data attributes, agent name, or data type name (e.g., email, agent name, or "leads"). list action only
skipintegerNo0Pagination offset (list only)
limitintegerNo10Maximum records to return (list only, default: 10 for LLM context)
group_by_agentbooleanNofalseWhen true with action="stats", returns per-agent breakdown instead of flat totals
include_facetsbooleanNofalseWhen true with action="list", adds filter-aware per-type and per-status facet counts to the response

Returns โ€‹

Return type depends on the action and group_by_agent flag:

ConditionReturn Type
action="list"PaginatedExtractedEntitiesResponse
action="get"ExtractedEntityDetailRead
action="stats" (default)StatsRead
action="stats" + group_by_agent=trueStatsByAgentRead

PaginatedExtractedEntitiesResponse (action="list"):

AttributeTypeDescription
.datalist[ExtractedEntityRead]List of collected data entries
.pagination.totalintTotal matching records
.pagination.skipintNumber of records skipped
.pagination.limitintRecords per page
.facetsEntityFacets | NoneFilter-aware facet counts. Present only when include_facets=True; None otherwise (additive, backward-compatible -- zero extra queries run when omitted)

Each ExtractedEntityRead has: id, entity_type_name, entity_type_icon, agent_name, status, created_at, attributes, confidence_score, plus the server-resolved identity fields display_name, contact_email, contact_phone, display_summary, session_channel (additive, nullable โ€” see the identity_field reference in Manage Resources).

EntityFacets (.facets, when include_facets=True):

AttributeTypeDescription
.entity_typeslist[TemplateCount]Per-template counts -- same shape as type_counts in StatsRead. Nonzero counts only, sorted by count descending. Ignores the template_name filter; applies every other active filter
.statusesdict[str, int]Count per status value (new, reviewed, actioned, archived). Ignores the status filter; applies every other active filter -- always includes archived counts even when archived records are excluded from .data

StatsRead (action="stats"):

AttributeTypeDescription
.totalintTotal records collected in the period
.status_countsdict[str, int]Breakdown by status: new, reviewed, actioned, archived
.type_countslist[TemplateCount]Templates with template_id, template_name, count
.agent_countslist[AgentCount]Agents with agent_id, agent_name, count
.period_daysint | NoneThe analysis period. None when days was omitted -- totals are all-time (no date cutoff)

StatsByAgentRead (action="stats", group_by_agent=true):

AttributeTypeDescription
.agentslist[AgentStatsRead]Per-agent breakdown (each has agent_id, agent_name, status_counts, type_counts, total)
.totalintGrand total across all agents
.period_daysint | NoneThe analysis period. None when days was omitted -- totals are all-time (no date cutoff)

gnosari_collected_data_delete โ€‹

Permanently delete collected data records (leads, feedback, etc.). Two-phase: preview first, confirm second. This is a separate tool from gnosari_collected_data โ€” there is no action="delete" on the read-only tool.

Annotations: readOnlyHint: false ยท destructiveHint: true ยท idempotentHint: true ยท openWorldHint: false

Parameters โ€‹

NameTypeRequiredDefaultDescription
entity_idslist[int]Yes-Ids of the collected records to permanently delete
confirmedbooleanNofalseMust be true to delete. When false, returns a confirmation summary and warning -- nothing is deleted

Returns โ€‹

  • confirmed=false โ†’ CollectedDataDeleteConfirmation: count (number of records that would be deleted), warning (human-readable irreversibility warning), confirm_instruction (how to proceed with the confirmed deletion)
  • confirmed=true โ†’ CollectedDataDeleteResult: {"deleted": 3}

Example โ€‹

python
# Phase 1: Preview
preview = gnosari_collected_data_delete(entity_ids=[123, 124, 125])
print(preview.warning)
# "This will permanently delete 3 collected record(s). This cannot be undone."

# Phase 2: Confirm (after user approval)
result = gnosari_collected_data_delete(entity_ids=[123, 124, 125], confirmed=True)
print(result.deleted)  # 3

Account-scoped: ids that don't belong to your account are silently skipped, so deleted reflects only your own rows.


Action: list โ€‹

Browse collected records -- leads, feedback, candidates, orders. Filter by agent, template, date range, status, or search text.

Examples โ€‹

See all data collected by a specific agent:

python
result = gnosari_collected_data(action="list", agent_id=123)
for entry in result.data:
    print(f"{entry.template_name}: {entry.status}")

Find all candidate applications in the last 30 days:

python
result = gnosari_collected_data(action="list", template_name="candidates", days=30)
print(f"Found {result.pagination.total} candidates")
for candidate in result.data:
    print(f"  - {candidate.attributes_summary}")

Search for a specific email:

python
result = gnosari_collected_data(action="list", search="john@example.com", days=5)
if result.pagination.total > 0:
    print(f"Found {result.pagination.total} records")

All reviewed leads this month:

python
result = gnosari_collected_data(action="list", template_name="leads", status="reviewed", days=30)

Paginate through large result sets:

python
page1 = gnosari_collected_data(action="list", skip=0, limit=10)
page2 = gnosari_collected_data(action="list", skip=10, limit=10)

Get facet counts alongside the results (for a type/status picker):

python
result = gnosari_collected_data(action="list", status="new", include_facets=True)
print(f"{result.pagination.total} new records")
for t in result.facets.entity_types:
    print(f"  {t.template_name}: {t.count}")
print(f"All statuses: {result.facets.statuses}")

template_name Resolution Logic โ€‹

The template_name parameter performs a case-insensitive lookup against all available templates for your account. If no match found, returns all data (no template filter applied).

Status Values โ€‹

StatusMeaningWhen Applied
newNewly extracted, not yet reviewedDefault status after extraction
reviewedReviewed and confirmed as accurateManually marked in dashboard
actionedAction taken on this dataAfter follow-up, outreach, etc.
archivedNo longer activeMoved to archive

Action: get โ€‹

Fetch ONE record's full detail by entity_id, including the per-attribute provenance -- which conversation message and verbatim quote each extracted value came from. Use this after action="list" to drill into a specific record.

Parameters โ€‹

entity_id is required for this action. All list-only parameters (template_name, days, status, search, skip, limit) are ignored.

Example โ€‹

python
record = gnosari_collected_data(action="get", entity_id=123)
print(f"{record.template_name}: {record.status}")
print(record.provenance)

Output:

python
{
  "full_name": {"message_id": 4821, "quote": "I'm John Smith"},
  "email": {"message_id": 4821, "quote": "john.smith@example.com"},
  "phone": {"message_id": None, "quote": "555-123-4567"},
}

Field Reference: provenance โ€‹

ExtractedEntityDetailRead.provenance is dict[str, dict] | None -- None for legacy or provenance-free entities. Each entry maps an attribute name to:

FieldTypeDescription
message_idint | NoneSession message the value was extracted from. None when the id could not be server-verified against the session's messages
quotestrVerbatim quote from that message supporting the value

Dangling id caveat: message_id has no foreign key to the session message table -- it is a point-in-time snapshot. Sessions hard-delete their messages, so a message_id can reference a message that no longer exists. Treat it as historical evidence, not a resolvable link; always fall back to quote when the id can't be resolved.

Field Reference: session_excerpt โ€‹

ExtractedEntityDetailRead.session_excerpt is list[SessionExcerptMessage] | None -- returned in the same response as the record detail, so no second fetch is needed to show the surrounding conversation. None (never an empty list) when there is nothing to show. Each entry is one conversation message:

FieldTypeDescription
idintSession message insertion-order id -- lets the client key excerpt entries to provenance.message_id citations
rolestr"user" or "assistant" -- system/tool turns are dropped
textstrMessage text, server-truncated to 500 chars with a trailing โ€ฆ when clipped
created_atdatetimeWhen the message was created

Selection is provenance-first: when the record's provenance cites message ids, the excerpt is those cited messages plus one adjacent message on each side (deduped, chronological by id, capped at 6). Otherwise it falls back to the last 6 visible (user/assistant) messages at or before the record's created_at.

Null contract: session-less records, records whose session was deleted (dangling session_id), and records with zero visible messages all return None for session_excerpt.


Action: stats โ€‹

Dashboard totals -- counts by template, status breakdown, trends. Use group_by_agent=True for per-agent breakdown.

Examples โ€‹

All-time (default -- days omitted):

python
stats = gnosari_collected_data(action="stats")
print(f"Total collected: {stats.total}")
print(f"New: {stats.status_counts['new']}")
for t in stats.type_counts:
    print(f"{t.template_name}: {t.count}")
# stats.period_days is None -- no date cutoff applied

Last 30 days:

python
stats = gnosari_collected_data(action="stats", days=30)
print(f"Total collected in last 30 days: {stats.total}")

Last 7 days for a specific agent:

python
stats = gnosari_collected_data(action="stats", agent_id=123, days=7)
print(f"Agent 123 collected {stats.total} records this week")

Per-agent breakdown in a single call:

python
stats = gnosari_collected_data(action="stats", group_by_agent=True, days=30)
for agent in stats.agents:
    print(f"{agent.agent_name}: {agent.total} records")
    print(f"  New: {agent.status_counts.get('new', 0)}")

Call Sequence Pattern โ€‹

Recommended workflow: Stats first, then list, then get for a single record's evidence.

python
# 1. Get the big picture
stats = gnosari_collected_data(action="stats", days=7)
print(f"Total collected this week: {stats.total}")

# 2. Drill into specific data
if stats.status_counts['new'] > 0:
    new_data = gnosari_collected_data(action="list", status="new", days=7)
    print(f"Processing {len(new_data.data)} new records...")
    for entry in new_data.data:
        print(f"  {entry.template_name}: {entry.attributes_summary}")

    # 3. Pull one record's full detail, incl. provenance and session excerpt, before acting on it
    detail = gnosari_collected_data(action="get", entity_id=new_data.data[0].id)
    print(detail.provenance)
    print(detail.session_excerpt)

Common Use Cases โ€‹

Daily lead review:

python
result = gnosari_collected_data(action="list", template_name="leads", status="new", days=1)

Weekly team standup:

python
stats = gnosari_collected_data(action="stats", group_by_agent=True, days=7)
print(f"This week: {stats.total} total")
for agent in stats.agents:
    print(f"  {agent.agent_name}: {agent.total}")

Agent performance check:

python
result = gnosari_collected_data(action="list", agent_id=123, days=1)
print(f"Agent collected {result.pagination.total} records today")

Best Practices โ€‹

  1. Start with stats - Get the overview before diving into details
  2. Use template_name instead of template_id - Much easier to remember "leads" than a numeric ID
  3. Use days parameter for relative dates - days=7 is simpler than calculating ISO dates
  4. Keep limit small for LLM context - Default of 10 prevents context window bloat
  5. Use status filters - Focus on actionable data with status="new"
  6. Use group_by_agent for comparisons - One call instead of per-agent loops

Next Steps โ€‹