Investigate an AI Agent Leak with SQL

Query a real incident database in your browser and export your findings.

Introduction

30 Second Summary

Headlines can make hidden online coordination sound certain. The raw evidence lets you decide whether the pattern holds up.

In this project, you will investigate reports of AI agents exchanging messages through public wikis inside Datasette Lite. You will use SQL to build a portable evidence package you control.

What You'll Build

Your SQL questions become browser-based evidence tables you can reproduce from a saved link.

By the end of this project, you'll have:

  • A message trail you can inspect from the table list down to one complete agent message.
  • A traffic breakdown that shows which wikis carried the most messages. You can also see which days were busiest.
  • A reproducible finding backed by a saved SQL query link. A CSV export preserves your result. A local SQLite database keeps the source evidence available.
  • Secret Mission: An optional challenge to push your investigation skills further.

Are there any prerequisites?

You need a modern browser plus basic SQL familiarity. Datasette Lite runs without an account, local installation, or payment card.

Before We Start

Before you open the Datasette Lite link or the published database link, this checkpoint locks in the purpose behind investigating agent messages with SQL. A modern browser with an internet connection is enough for a project that requires no software installation or account.

Load the Incident Database

The incident evidence lives in a 68MB SQLite database. Before you can ask questions with SQL, the published file must finish loading in your browser.

Datasette Lite reads the file inside your browser without an installation or account. In this step, you will load the published database until its table list is visible.

In this step, get ready to:
  • Load the published incident database in Datasette Lite.
  • Confirm the database table list is visible in your browser.
  • Keep the loaded database available in your browser session.
Load the published database

The browser fetches the entire database before it can show the data. A quiet tab during this 68MB download is normal, especially on a slower connection.

  • Follow the Datasette Lite link from earlier in your browser.
  • Keep the new tab open while the published database loads.
  • Wait for the page to finish loading.

When the download completes, you will see the incident database page in place of the loading state.

Database still loading?

  • Wait a little longer because the 68MB file can take time on a slower connection.
  • Confirm your internet connection is active.
  • Follow the Datasette Lite link again after your connection is stable.

Help me diagnose a stalled Datasette Lite database load.

Verify the database load

The table list shows that Datasette Lite can read the structure of the published file. It is your first visible proof that the evidence is ready for investigation.

Before you check the finished page, picture the visible sign you expect to confirm that the database is ready.

  • Inspect the finished Datasette Lite page to determine whether the load succeeded.

You should see the published AI-agent incident database with its table list visible. This confirms that the database is loaded in the current browser session.

  • Keep the Datasette Lite tab open for the next investigation step.

Your first win is secured because the published evidence is loaded with its table list ready to inspect.

What did Datasette Lite load?

Datasette Lite runs SQLite through WebAssembly inside your browser. That makes the published file queryable without a local server.

The current browser session now holds the loaded database. The visible table list confirms that its structure is available.

The evidence is loaded. Next, you will start examining what the incident database contains.

Inspect Agent Messages

Your browser now holds the published incident database inside Datasette Lite. The visible table list proves the SQLite file loaded successfully.

A row becomes useful evidence when you can place it on a specific wiki at a specific time. Reading the entire message keeps your interpretation grounded in the source.

In this step, you will open the largest message table. You will sort it chronologically before reading one complete record.

In this step, get ready to:
  • Open the largest agent-message table.
  • Map the source field plus the time field.
  • Read one complete message in chronological context.
Open the largest message table

The row counts reveal where most of the incident evidence lives. The largest content table gives you the broadest collection of agent messages to inspect.

  • Switch back to the database table list from earlier.
  • Compare the row counts shown beside the table names.
  • Select the agent-message table with the highest count.
  • Scan the opened rows for a column containing message-sized text.

You should see a grid of records containing substantial blocks of agent-written text. That confirms you found the message table.

Rows do not contain agent messages?

  • Check that you selected a content table instead of a metadata table.
  • Try the next-largest content table if the rows contain no message-sized text.

Ask for help identifying the correct table without guessing its name: Which table contains the agent messages in my Datasette Lite database?

Identify the source and time fields

A table's schema describes the fields available in every row. Finding the source field plus the time field can be fiddly because scraped datasets often use short column names.

  • Scan the column headings for the field that names the wiki or site.
  • Record the exact source field name here: your wiki field name.
  • Scan the column headings for the field that stores the date or timestamp.
  • Record the exact time field name here: your date or timestamp field name.
  • Use the sort control attached to the date or timestamp heading.
  • Set older records to appear before newer records.

You should now see the date or timestamp values progress chronologically down the table. The source field remains visible beside each message row.

Why identify these fields now?

The source field tells you which wiki carried each message. The time field places that message within the incident timeline.

These exact field names become the anchors for grouping the evidence later.

Read one complete agent message

The table grid gives you a scan-friendly preview of each record. A linked record view gives one message enough space to read without losing its source details.

  • Choose one row that contains message text.
  • Open that row from its linked record identifier.
  • Locate the beginning of the message text.
  • Read the message through its final line.
  • Find the source value under your wiki field name.
  • Find the time value under your date or timestamp field name.

Good work. You now have one complete agent message anchored to its wiki source plus its place in the incident timeline.

Before the final check, which field should explain where the message appeared? Which field should explain when it appeared?

  • Return to the sorted table using your browser's back navigation.
  • Confirm the active sort belongs to your date or timestamp field name.
  • Confirm your wiki field name remains visible in the table.
  • Confirm the time values progress from older records to newer records.

You'll see the message rows in chronological order. The wiki field plus the date or timestamp field remain visible for the next stage of analysis.

Sort order disappeared?

  • Return with your browser's back navigation so the previous table state can be restored.
  • Reapply the date or timestamp field's sort control if the rows no longer follow chronological order.

Ask for help restoring the sorted table state: Why did my Datasette Lite table lose its date sort?

You have found the messages behind the incident story. Next, you will group those rows by wiki and day to reveal where the traffic concentrated.

Explore Traffic with Facets

You have already opened the largest message table in Datasette Lite. You also read one agent exchange from start to finish.

A facet groups repeated values into count summaries. Those summaries reveal where the messages clustered over time without writing SQL.

In this step, get ready to:
  • Group the message rows by wiki site.
  • Group the message timestamps by day.
  • Compare the facet counts to find the busiest sites and dates.
Group messages by wiki

The wiki field identifies the public site that carried each message. Faceting this field converts the message rows into site-level traffic counts.

  • Select the small action control beside the wiki field's column heading.
  • Click Facet by this.

You should see a facet summary containing wiki values with counts beside them. The message rows should remain visible on the same page.

What Does a Facet Show?

Datasette Lite computes a count for each distinct value in the selected field. The wiki facet turns thousands of message rows into a short site comparison.

Group timestamps by day

A timestamp contains more detail than this comparison needs. A date facet collects timestamps from the same calendar day into one count.

  • Locate Suggested facets near the table.
  • Click the link for your date or timestamp field with (date) beside it.

You should see a second facet summary containing calendar dates with counts beside them. You now have a site view plus a daily view of the same traffic.

Missing a Facet Summary?

  • Confirm you are still viewing the largest agent-message table.
  • Check that the date or timestamp field remains visible in the table.
  • Reload the table once if the date suggestion does not appear.

Help me restore the missing Datasette Lite facet summary.

Compare the traffic counts

The number beside each facet value represents its message volume. Large differences show where traffic was concentrated.

Before you compare the wiki counts, predict which site leads. Before you compare the date counts, predict which day is busiest.

  • Identify the site with the largest total from the wiki facet counts.
  • Identify the busiest day from the date facet counts.
  • Compare the leading wiki count with the remaining wiki counts.

You should be able to identify the highest wiki count. You should also be able to identify the highest daily count.

Both facet summaries should remain visible beside the agent-message rows.

You have turned thousands of messages into a clear traffic map. Next, you will test this visual finding with your own SQL query.

Query Messages by Day and Wiki

Your facets revealed where agent activity clustered across wiki sites and dates. Visual exploration is quick. A forensic finding also needs logic that another person can rerun.

A SQL query makes that logic explicit. You’ll group messages by calendar day and wiki. You’ll verify one result against the facets before preserving its reproducible URL.

In this step, get ready to:
  • Translate the identified table fields into a grouped SQL query.
  • Compare one query count with the existing facet results.
  • Save the reproducible query URL in your browser.
Build the grouped count query

Grouping converts many individual messages into a smaller summary table. Each group represents one calendar day on one wiki.

The Datasette Lite query editor lets you express those groups directly. The result becomes evidence you can reproduce from the browser URL.

  • Switch from the largest agent-message table to the database query editor.
  • Complete the query placeholders with the table name and field names you identified earlier:
-- Group each message into a calendar day and wiki
select
  substr("[[DATE_FIELD="identified date or timestamp field name"]]", 1, 10) as day,
  "[[WIKI_FIELD="identified wiki field name"]]" as wiki,
  count(*) as message_count
from "[[MESSAGE_TABLE="largest agent-message table name"]]"
group by day, wiki
order by day, message_count desc

What does this query do?

  • The substr() expression keeps the calendar-date portion of each timestamp.
  • The GROUP BY clause creates one group for every unique day and wiki combination.
  • The count(*) expression counts the messages inside each group.
  • The final ordering keeps dates together. Higher-traffic wikis appear first within each date.

Before you run the query, how many columns do you expect the result table to contain?

  • Run the query using the execution control beside the editor.

You should see three columns for the day, wiki, and message count. Each result row should represent one unique day and wiki combination.

That is your first reproducible finding. Thousands of raw messages are now condensed into daily traffic totals for each wiki.

Query did not produce grouped results?

  • Check that each placeholder contains the exact schema name shown in the largest agent-message table.
  • Confirm that the date placeholder uses the identified date or timestamp field.
  • Confirm that the wiki placeholder uses the same field as the existing wiki facet.

Ask for help with the query structure: Why is my SQL query not grouping the incident messages by day and wiki?

✔️ Awesome, I've got everything!

Your grouped query is complete. Keep the result page available for the facet comparison.

ⓧ I'd like to double check the full code

-- Group each message into a calendar day and wiki
select
  substr("[[DATE_FIELD="identified date or timestamp field name"]]", 1, 10) as day,
  "[[WIKI_FIELD="identified wiki field name"]]" as wiki,
  count(*) as message_count
from "[[MESSAGE_TABLE="largest agent-message table name"]]"
group by day, wiki
order by day, message_count desc
Compare one count with the facets

An aggregate becomes more trustworthy when an independent view agrees with it. Your existing facets provide that cross-check without changing the underlying database.

  • Choose one row from the SQL result table to audit.
  • Record its day here: selected calendar day.
  • Record its wiki here: selected wiki.
  • Record its message count here: SQL message count.
  • Switch back to the faceted agent-message table from earlier.
  • Select selected wiki in the existing wiki facet.

Before you apply the day facet, do you expect the filtered total to match the SQL count exactly?

  • Select selected calendar day in the existing day facet.

The filtered facet total should match SQL message count. The agreement proves that your query groups the same rows as the visual controls.

Counts do not match?

  • Confirm that both views use the same wiki value.
  • Check that the day facet matches the date produced by the query.
  • Clear any extra table filters left over from your earlier exploration.

Why does my SQL message count differ from the matching Datasette Lite facet count?

Save the reproducible query link

Datasette Lite stores the query state in the result page URL. Saving that URL preserves the exact SQL instead of leaving you with a copied number that has lost its method.

  • Switch back to the SQL result page from earlier.
  • Select the full query URL in your browser address bar.
  • Copy the selected URL.
  • Open a new browser tab using the plus button in the tab bar.
  • Paste the copied query URL into the address bar.

Before you load the URL, do you expect it to restore only the database or the complete grouped result?

  • Press Enter to load the pasted URL.

You should see the same SQL and the same three-column result table. The browser address should contain encoded query text that makes the finding reproducible.

  • Bookmark the verified result page using your browser controls.

You now have a saved investigation path that another person can rerun. Your result includes both the finding and the method that produced it.

Your query is grouped, checked, and saved as a reproducible link. Next up, you’ll export the result as CSV and keep a local copy of the incident database.

Export Your Evidence

Your saved SQL query in Datasette Lite now returns one row for each day and wiki. Its message counts match the traffic facets you explored.

A finding can disappear when it lives only in a browser session. You will preserve the complete evidence package in local files plus a reproducible query URL.

In this step, get ready to:
  • Export the saved SQL result as a CSV file.
  • Download the published SQLite database for local access.
  • Save the reproducible Datasette Lite query URL.
Export CSV

A CSV export freezes your result rows in a portable file. You can inspect the evidence without depending on the current Datasette Lite session.

Before you export, predict whether the CSV will preserve every row in the result table.

  • Switch back to the Datasette Lite query result from earlier.
  • Click this data as CSV below the result table.

You will see the query output as comma-separated rows. The column headings should match the result table.

  • Save the CSV view by pressing Cmd+S on macOS or Ctrl+S on Windows.
  • Keep the .csv extension in the save dialog.
  • Select your Downloads folder as the destination.
  • Click Save.
  • Open the downloaded .csv file from your browser downloads list.

You should see the same column headings and the same number of data rows as the Datasette Lite result. That result now exists independently of the browser page.

  • Return to the Datasette Lite query result tab.

CSV File Missing?

  • Use your browser's page-saving control if the CSV opens as a page without downloading.
  • Return to the saved query result if the exported rows differ from your grouped result.
  • Keep the .csv extension if your browser tries to save the file as plain text.

Why does my exported CSV differ from my Datasette Lite query result?

Download SQLite

The CSV preserves your finding. A local database copy preserves the source material behind that finding.

The database is about 68MB. A slower connection may need a little time to finish the download.

You now have an independent copy of the incident database. The file remains available even if the hosted page disappears.

Database Download Stalled?

  • Check the browser download progress before starting another copy.
  • Retry the published database link after confirming your internet connection is stable.
  • Confirm the completed file ends in .db.

Why is my incident database download incomplete or stalled?

Bookmark

Datasette Lite stores your SQL in the page URL. A bookmark keeps the path from the source database to your exact result.

  • Switch back to the saved query result tab.
  • Confirm the browser address bar still contains the long URL produced by your query.
  • Save the current query as a bookmark by pressing Cmd+D on macOS or Ctrl+D on Windows.
  • Accept the suggested bookmark name by pressing Enter.

Before you reopen the bookmark, predict whether it restores the database home page or the exact query result.

  • Open a new browser tab by pressing Cmd+T on macOS or Ctrl+T on Windows.

The fresh tab reloads the database before running the saved query. Give it time to process the 68MB file if the table list takes a while to appear.

  • Load the bookmark you just saved from your browser's bookmarks menu.

You should see the message-count result with one row per day-and-wiki combination. This proves the bookmark preserves the query plus its result.

Bookmark Opens the Wrong Page?

  • Create the bookmark from the query result tab if the current bookmark opens only the database table list.
  • Wait for the database load to finish if the table list appears before the query result.
  • Keep the original query tab open while testing the replacement bookmark.

Why does my Datasette Lite bookmark open the database without restoring my SQL result?

  • Open your Downloads folder in Finder on macOS or File Explorer on Windows.

You should see the downloaded CSV result plus collusion-wiki.db. Your saved bookmark should reopen the same grouped result in Datasette Lite.

You now own the result file and the source database. You also have a saved URL that reproduces how you reached the finding.

Secret mission

Build a Defensible Traffic Spike Finding

Turn one high-traffic wiki-day result into a defensible incident finding. Reproduce its count with the existing facets. Inspect a source message before stating a careful conclusion.

Clean Up Your Resources

Clean Up Your Resources

Your investigation is complete, so choose whether to keep the evidence, pause the browser session, or delete your local artifacts. Everything ran in your browser with no account or paid resource, so there are no ongoing costs.

Resources you used:

  • A browser session in Datasette Lite with the published incident database loaded.
  • A downloaded CSV export containing message counts by day and wiki.
  • A local copy of the published incident SQLite .db database file.
  • A saved query URL that reproduces your SQL result.

Keep everything running

No action needed. Choose this if you want to continue investigating the messages or share your finding.

  • Keep the Datasette Lite browser tab open while you continue investigating.
  • Keep the downloaded CSV export as a record of your result.
  • Keep the local .db file as your copy of the incident dataset.
  • Keep the saved query URL so you can reproduce the message-count result.

Your local database copy remains available even if the hosted page disappears. The saved query URL preserves the exact finding you produced.

Pause - I'll come back to this later

This option closes the active browser session while keeping your evidence for later. Your local files remain on your computer.

  • Close the Datasette Lite browser tab from this project.
  • Leave the downloaded CSV export in its current saved location.
  • Leave the local .db file in its current saved location.
  • Leave the saved query URL in the location where you stored it.

Your saved query URL gives you the reproducible result again when you return. Your local database copy lets you continue with the same source data.

Delete - I don't want to use this again

This option removes the local evidence plus the saved link. The published source remains online because it is not your resource.

  • Close the Datasette Lite browser tab from this project.
  • Remove the saved query URL from the location where you stored it.

The remaining resources are the two downloaded files. Use the instructions for your operating system to remove them.

macOS

  • Use your browser's download history to locate the downloaded CSV export in the macOS file manager.
  • Delete the downloaded CSV export from this project.
  • Use your browser's download history to locate the downloaded SQLite .db file in the macOS file manager.
  • Delete the downloaded SQLite .db file from this project.

Windows

  • Use your browser's download history to locate the downloaded CSV export in the Windows file manager.
  • Delete the downloaded CSV export from this project.
  • Use your browser's download history to locate the downloaded SQLite .db file in the Windows file manager.
  • Delete the downloaded SQLite .db file from this project.
  • Check the location where you stored the saved query URL.
  • Check the former saved locations of the two downloaded files.

The query URL should no longer appear in its saved location. The CSV export and local database file should no longer appear in their former saved locations.

Nice Work!

Nice Work!

Investigation complete. You turned a published AI-agent incident database into findings that anyone can reproduce from your saved query URL.

You've learned how to:

  • Investigate a real SQLite database with Datasette Lite in your browser. You sorted the largest agent-message table by its date or timestamp field. You also read one complete message.
  • Reveal traffic patterns by faceting message rows by wiki. You grouped those rows by day. This showed which sites carried the most agent-message traffic.
  • Write a SQL query that counts messages for each day-and-wiki combination. You checked the result against the facet counts. You created a CSV export of your findings. You downloaded a local database copy. You also saved the reproducible query URL.
  • Secret Mission: Take on the optional challenge to push your SQL investigation skills further.

Ready to quiz yourself?