<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lorry Zhang</title>
    <description>The latest articles on DEV Community by Lorry Zhang (@lorry_zhang_6c8c50ea513c3).</description>
    <link>https://dev.to/lorry_zhang_6c8c50ea513c3</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4229547%2Fa8a6951a-e943-4eec-ac4a-44d25e0efbba.png</url>
      <title>DEV Community: Lorry Zhang</title>
      <link>https://dev.to/lorry_zhang_6c8c50ea513c3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lorry_zhang_6c8c50ea513c3"/>
    <language>en</language>
    <item>
      <title>Two Weeks of Study Notes: What Can an Agent Actually Tell Me?</title>
      <dc:creator>Lorry Zhang</dc:creator>
      <pubDate>Fri, 06 Nov 2026 14:21:05 +0000</pubDate>
      <link>https://dev.to/lorry_zhang_6c8c50ea513c3/two-weeks-of-study-notes-what-can-an-agent-actually-tell-me-46gf</link>
      <guid>https://dev.to/lorry_zhang_6c8c50ea513c3/two-weeks-of-study-notes-what-can-an-agent-actually-tell-me-46gf</guid>
      <description>&lt;p&gt;On Sunday evening, you want to know how much of the past two weeks went into reading about programming and how much into practice. The arithmetic is easy enough. The minutes live in a timer app, the topics in your notes, and the reason one practice session stopped in a task comment.&lt;/p&gt;

&lt;p&gt;You can collect those entries, make a table, and hand it to an agent. Once is manageable; every Sunday it becomes its own task. A controlled script or business backend could submit a small, consistent record when each session ends; you retrieve those records at review time.&lt;/p&gt;

&lt;p&gt;A table pasted today answers today's question. Next week's sessions will not automatically enter that conversation, and a chat summary is not a substitute for the original entries. Someone still needs to connect the recording tool; existing note apps do not suddenly sync themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agree on what a session means
&lt;/h2&gt;

&lt;p&gt;Settle four things first: end time, topic, recorded minutes, and what "completed" or "interrupted" means. Does a break followed by more practice count as one session or two? Decide before collecting months of inconsistent entries. A controlled reporter submits each session to an external store; an authorized agent reads the details later. If a phone app collects the data, do not embed a long-lived write token in the app.&lt;/p&gt;

&lt;p&gt;These seven records are invented, not actual user data. Dates use Singapore time (Asia/Singapore). Minutes are self-reported, not a measure of attention or mastery.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Week&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Topic&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Recorded outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Week 1&lt;/td&gt;
&lt;td&gt;October 20&lt;/td&gt;
&lt;td&gt;Reading&lt;/td&gt;
&lt;td&gt;30 minutes&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Week 1&lt;/td&gt;
&lt;td&gt;October 22&lt;/td&gt;
&lt;td&gt;Reading&lt;/td&gt;
&lt;td&gt;25 minutes&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Week 1&lt;/td&gt;
&lt;td&gt;October 24&lt;/td&gt;
&lt;td&gt;Coding practice&lt;/td&gt;
&lt;td&gt;20 minutes&lt;/td&gt;
&lt;td&gt;Interrupted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Week 2&lt;/td&gt;
&lt;td&gt;October 27&lt;/td&gt;
&lt;td&gt;Reading&lt;/td&gt;
&lt;td&gt;15 minutes&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Week 2&lt;/td&gt;
&lt;td&gt;October 29&lt;/td&gt;
&lt;td&gt;Coding practice&lt;/td&gt;
&lt;td&gt;45 minutes&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Week 2&lt;/td&gt;
&lt;td&gt;October 31&lt;/td&gt;
&lt;td&gt;Coding practice&lt;/td&gt;
&lt;td&gt;40 minutes&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Week 2&lt;/td&gt;
&lt;td&gt;November 1&lt;/td&gt;
&lt;td&gt;Coding practice&lt;/td&gt;
&lt;td&gt;35 minutes&lt;/td&gt;
&lt;td&gt;Interrupted&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The calendar weeks are October 19–25 and October 26–November 1, 2026. In an authorized behavior-event schema, &lt;code&gt;scene_type=learning&lt;/code&gt; and &lt;code&gt;action_type=study_session&lt;/code&gt; could identify these records. Put the topic in a queryable &lt;code&gt;target_id&lt;/code&gt;; store minutes and outcome in &lt;code&gt;extra_params&lt;/code&gt; to read after retrieval. The October 29 session, for example, has &lt;code&gt;target_id=coding&lt;/code&gt;, &lt;code&gt;minutes=45&lt;/code&gt;, and &lt;code&gt;outcome=completed&lt;/code&gt;. An actual report also needs the schema's required source and time fields and a valid write credential.&lt;/p&gt;

&lt;p&gt;Query by &lt;code&gt;scene_type&lt;/code&gt;, &lt;code&gt;action_type&lt;/code&gt;, and time, then read the returned minutes. Nested keys inside &lt;code&gt;extra_params&lt;/code&gt; cannot be used as direct filters, and the service does not automatically aggregate them. Adding up seven complete records is straightforward. Finding every session longer than two hours over six months would require multiple bounded queries and completeness checks, or a separately designed queryable field. Write and read permissions are separate; an accepted report may not be visible until asynchronous loading finishes.&lt;/p&gt;

&lt;p&gt;If your notes are spread across apps, choose a trusted script to translate them, and decide what should never be uploaded. The full text of a personal journal adds little to this particular reading-versus-practice question.&lt;/p&gt;

&lt;p&gt;Give each study session a stable &lt;code&gt;session_id&lt;/code&gt;; here it identifies a study session, not an agent chat. Suppose the phone loses its connection after handing the record to a controlled reporter, which then retries an uncertain submission. Two accepted reports get different server-generated &lt;code&gt;event_id&lt;/code&gt; values even though there was only one 45-minute practice session. When reading, flag records with the same &lt;code&gt;session_id&lt;/code&gt; and check the source before adding them up as 90 minutes. That is a convention for your reporter and analysis, not a promise that ingestion automatically deduplicates retries.&lt;/p&gt;

&lt;h2&gt;
  
  
  What seven records can answer
&lt;/h2&gt;

&lt;p&gt;Suppose all seven have loaded and the query has not hit its limit. You could ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Compare my study records from October 19–25 and October 26–November 1, 2026. Add up minutes by topic and show how much I recorded for reading and practice each week. Mark unrecorded days as unknown.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent can add the seven rows: Week 1 has 75 recorded minutes, 55 of reading and 20 of coding practice. Week 2 has 135, 15 of reading and 120 of practice. That is 60 more recorded minutes and a clear shift in the mix toward practice. Week 1 has two sessions marked completed and one interrupted; Week 2 has three completed and one interrupted. This is arithmetic over retrieved detail records, not a claim of server-side analytics.&lt;/p&gt;

&lt;p&gt;Those totals include the 20- and 35-minute interrupted practice sessions: time spent before the interruption still counts as study time. Ask instead for minutes of &lt;em&gt;completed&lt;/em&gt; coding practice and the answer changes to zero in Week 1 and 85 in Week 2 (45 plus 40). The records are identical; the definition of what to add has changed. That definition is worth stating in the question.&lt;/p&gt;

&lt;p&gt;A narrower follow-up is possible: "Was practice concentrated on the weekend in Week 2?" October 31 and November 1 contain 40 and 35 recorded minutes, respectively. That is 75 of the 120 practice minutes recorded that week. It says where the logged time falls; it does not prove you were more focused on weekends.&lt;/p&gt;

&lt;p&gt;The seven rows do not tell us the exact day the pattern changed or whether learning became more effective. An unrecorded day is unknown, not proof of no study. If a planned break was marked "interrupted" in Week 1 but only phone calls got that label in Week 2, even the interruption counts are not comparable.&lt;/p&gt;

&lt;p&gt;If the query returns five entries instead of seven, find the missing two before drawing a conclusion. The service filters by receipt time; sessions reported late may fall outside the chosen window. Queries have time and result limits, so a longer history needs multiple windows and, where applicable, pages with a completeness check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before tracking anything else
&lt;/h2&gt;

&lt;p&gt;Habits and spending raise similar questions, but renaming a study event does not create a ready-made finance feature. A spending record needs amounts, currencies, categories, and a rule for refunds. Count a transfer as spending and record it again at the receiving account, and a fast total is still wrong. Be particularly selective about reporting financial or health details, who may read them, and how long they remain available. Health records are no substitute for medical judgment.&lt;/p&gt;

&lt;p&gt;Start by noting the topic, minutes, and outcome at the end of each session for two weeks. At review time, check that the records were all retrieved before comparing them. If you still have to reconstruct half your studying from memory, fix the reporting habit or integration before connecting another source.&lt;/p&gt;

&lt;p&gt;Project website: &lt;a href="https://d2ggep2t73r4ny.cloudfront.net/" rel="noopener noreferrer"&gt;https://d2ggep2t73r4ny.cloudfront.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Technical and business discussion: &lt;a href="mailto:lorry@antlertec.com"&gt;lorry@antlertec.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>When the 2 a.m. Sync Fails, What Should an Agent Look Up?</title>
      <dc:creator>Lorry Zhang</dc:creator>
      <pubDate>Fri, 06 Nov 2026 14:19:52 +0000</pubDate>
      <link>https://dev.to/lorry_zhang_6c8c50ea513c3/when-the-2-am-sync-fails-what-should-an-agent-look-up-2d2j</link>
      <guid>https://dev.to/lorry_zhang_6c8c50ea513c3/when-the-2-am-sync-fails-what-should-an-agent-look-up-2d2j</guid>
      <description>&lt;p&gt;Imagine a sync job that starts at 2 a.m. and has produced nothing by morning. You give its code to an agent and ask, "Where did it get stuck?" It can find the timeout handler and retry settings. To find out how long this run lasted or how many times it retried, it needs a record from the run.&lt;/p&gt;

&lt;p&gt;Logs and dashboards probably contain some of those facts. Manually pulling them into a chat is fine once in a while. A nightly job benefits from a fixed reporting convention, though: by the time something fails, you should not have to hunt through old logs to learn how long the previous run took.&lt;/p&gt;

&lt;p&gt;The job can report a few key events as it runs, and an external system can retain them. When something goes wrong, the agent retrieves records by job ID and time. Those details do enter its analysis context, so decide which fields are safe to report and who can read them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Record the moments that matter
&lt;/h2&gt;

&lt;p&gt;Record the start and end of a run, its outcome, duration, and retry count. The job name &lt;code&gt;nightly-sync&lt;/code&gt; identifies a series of executions; a different &lt;code&gt;trace_id&lt;/code&gt; identifies each execution and connects its events. A scheduler restart should get a new ID. It should not be confused with an internal retry in the same run.&lt;/p&gt;

&lt;p&gt;Define where a duration starts. If the job is scheduled at 02:00, waits a minute for a worker, and finishes at 02:02, you can report two minutes since scheduling or one minute of execution. Both can be useful, but they cannot be compared as if they were the same metric. In this example, &lt;code&gt;duration_ms&lt;/code&gt; runs from actual execution start to the reported outcome and includes time spent waiting between internal retries.&lt;/p&gt;

&lt;p&gt;The path is short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Job or app --report event--&amp;gt; Validate and store --retrieve on demand--&amp;gt; Agent --analyze--&amp;gt; Person
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An existing event platform may be enough. For small scripts and services scattered across systems, a shared reporting API is easier to govern than giving an agent direct read access to each production database. The agent gets a scoped read credential for the project.&lt;/p&gt;

&lt;p&gt;Keep full logs in their usual place; they may contain secrets, customer details, and irrelevant stack traces. Report the small set of facts the agent will need: job name, run ID, result, and duration. Missing outcome data cannot be reconstructed later from a clever prompt.&lt;/p&gt;

&lt;p&gt;Similarly, define &lt;code&gt;retry_count&lt;/code&gt; as attempts made within this execution. If the scheduler starts a new process after a failure, that is another run, not an additional internal retry of the first one. A batch ID may be worth retaining with the event, but one placed in &lt;code&gt;extra_params&lt;/code&gt; can only be read after retrieval. Frequent lookup by batch needs a planned queryable field.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two nights, two outcomes
&lt;/h2&gt;

&lt;p&gt;Both runs below are invented, not a real incident. On failure, &lt;code&gt;nightly-sync&lt;/code&gt; submits an event under an active, authorized behavior-event schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schema_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default_behavior_events"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schema_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"report_source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"be"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"client_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-11-05T02:02:00+08:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scene_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"scheduled_job"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"action_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run_failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"job"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nightly-sync"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target_value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"trace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"trace-job-demo-002"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"extra_params"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"duration_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"retry_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the November 5 job starts at 2 a.m. Singapore time and reports failure 120 seconds later, so &lt;code&gt;client_time&lt;/code&gt; is 2:02 a.m. &lt;code&gt;target_id&lt;/code&gt; is queryable. The duration and retry count in &lt;code&gt;extra_params&lt;/code&gt; can be read after retrieving the record, but its nested keys cannot be used as ordinary query filters. The &lt;code&gt;trace_id&lt;/code&gt; can connect this run to other evidence; a comparison with yesterday first requires that both runs use the same job identity and reporting convention.&lt;/p&gt;

&lt;p&gt;The invented November 4 run also starts at 2 a.m. Singapore time. It reports &lt;code&gt;run_completed&lt;/code&gt; at 2:00:45 a.m., with &lt;code&gt;duration_ms=45000&lt;/code&gt; and &lt;code&gt;retry_count=0&lt;/code&gt;. These two reported durations differ by 75 seconds. They do not tell us whether the job has been slowing down all week, or which downstream service caused the timeout.&lt;/p&gt;

&lt;p&gt;Check the job version, input size, and definition of completion before calling this a slowdown. Processing a hundred thousand rows one night and a hundred the night before changes the comparison. The schema has an &lt;code&gt;app_version&lt;/code&gt; field if you need to track a job version. For input size, decide what is safe to report and whether it belongs in an extension attribute or a separately planned queryable field.&lt;/p&gt;

&lt;p&gt;HTTP &lt;code&gt;202&lt;/code&gt; acknowledges receipt by the message pipeline; the event may not yet be queryable. Save each response's event ID and &lt;code&gt;server_time&lt;/code&gt;, then check again after asynchronous loading. Assume both receipts are within November 3 at 16:00 through November 5 at 16:00 UTC, the server-time window corresponding to November 4 and 5 in Singapore. A late report could be received after that window and would need a separate query.&lt;/p&gt;

&lt;p&gt;If the reporting client disconnects before receiving the response, the state is less clear: the runner may have submitted the failure event without seeing the acknowledgment. Reconcile before retrying rather than declaring the platform missed it. Conversely, retrieving a &lt;code&gt;run_failed&lt;/code&gt; event only tells you what the runner reported; it does not prove that every expected output row is absent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare the runs
&lt;/h2&gt;

&lt;p&gt;An engineer could ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find &lt;code&gt;nightly-sync&lt;/code&gt; events from November 3, 2026, 16:00 to November 5, 2026, 16:00 UTC. Compare the November 4 and 5 runs in Singapore time. List each run ID, outcome, duration, and retry count, then inspect where the timeout could occur in the code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent uses its read credential to query by server time and &lt;code&gt;target_id&lt;/code&gt;, then compares the records with the code's timeout and retry paths. In Codex, a configured MCP tool can provide that query. The &lt;a href="https://developers.openai.com/codex/mcp" rel="noopener noreferrer"&gt;Codex documentation&lt;/a&gt; covers the connection.&lt;/p&gt;

&lt;p&gt;Assuming both events have loaded and the query has not reached its limit, the answer might be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The November 5 run reported &lt;code&gt;run_failed&lt;/code&gt; with &lt;code&gt;timeout&lt;/code&gt; after 120 seconds and one internal retry. November 4 reported &lt;code&gt;run_completed&lt;/code&gt; after 45 seconds with no retry. That is a 75-second difference. We still do not know which dependency stalled; check the failed run's logs and downstream calls using its &lt;code&gt;trace_id&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The timeout branch in the code suggests where to look, but it does not prove this run passed through it. If the query is incomplete, the answer needs to say which records it actually saw.&lt;/p&gt;

&lt;p&gt;Use the failed run's &lt;code&gt;trace_id&lt;/code&gt; to find its execution logs. Did the internal retry occur before a connection was established, halfway through reading, or while writing the output? A slow dependency, a timeout threshold set too low, and queue time mistakenly included in execution time could all surface as &lt;code&gt;target_value=timeout&lt;/code&gt;. Timing for the corresponding downstream call is what would let you narrow the cause.&lt;/p&gt;

&lt;p&gt;Check &lt;code&gt;trace_id&lt;/code&gt; before comparing counts. A scheduler restart is a separate execution; mixing its duration and retries with the first run would corrupt the diagnosis. If a query fills its &lt;code&gt;limit&lt;/code&gt;, narrow the window or raise the total within the policy and follow a returned cursor for subsequent pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the failure paths first
&lt;/h2&gt;

&lt;p&gt;In this example, &lt;code&gt;duration_ms&lt;/code&gt; and &lt;code&gt;retry_count&lt;/code&gt; live in &lt;code&gt;extra_params&lt;/code&gt;. You can inspect them after retrieval but cannot filter directly on those nested keys. A standing question such as "which jobs ran longer than two minutes?" needs a queryable field or another analytics path. Keep reporting and reading credentials separate, and keep secrets and unnecessary personal data out of the event. The current production defaults cap a page at 100 rows and a time window at 31 days. You can query several windows, but that alone does not turn detail records into a trustworthy aggregate trend.&lt;/p&gt;

&lt;p&gt;The meaning of &lt;code&gt;run_completed&lt;/code&gt; matters too. It should mean that this execution finished according to the runner's contract. If the business question is whether the synced data passed a completeness check, report that check separately. The 45-second success record alone cannot establish that every output row was correctly stored the night before.&lt;/p&gt;

&lt;p&gt;Use a dedicated job to report one success and one failure. Save both &lt;code&gt;202&lt;/code&gt; receipts, wait until the records are queryable, and ask the agent to compare them. Then delay one report and see whether it confuses "not visible yet" with "never ran." That small test says more about this workflow than a fluent incident summary.&lt;/p&gt;

&lt;p&gt;Project website: &lt;a href="https://d2ggep2t73r4ny.cloudfront.net/" rel="noopener noreferrer"&gt;https://d2ggep2t73r4ny.cloudfront.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Technical and business discussion: &lt;a href="mailto:lorry@antlertec.com"&gt;lorry@antlertec.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>automation</category>
      <category>debugging</category>
    </item>
  </channel>
</rss>
