Agents for Humans: AgentCore Runtime sidecar, watchdog stays on systemd
This is the third post about Papelito, an Everyday Agents entry that reads Kindergarten paper and tracks the case through its reminder window. The first post covers the product boundary and the second covers the tools. This one explains the live AgentCore Runtime sidecar and why the daily watchdog remains on systemd.
This is the third post about Papelito, an Everyday Agents entry that reads Kindergarten paper and tracks the case through its reminder window. The first post covers the product boundary and the second covers the tools. This one explains the live AgentCore Runtime sidecar and why the daily watchdog remains on systemd.
What runs where today
Piece | Where it runs | Why |
|---|---|---|
The agent and its tools | Strands Agents SDK and Python on a local machine | The local workflow stays with its case file |
Vision and text models | Zen through an OpenAI-compatible gateway | Uses deepseek-v4-flash-vision-exp for photos and deepseek-v4-flash for text |
Case file | SQLite on the local machine | Contains the case state |
Photos and generated artifacts | Local disk | Remain with the case |
Web page | FastAPI on the household machine; separate Lightsail judge sandbox | Household data stays local; judge data is synthetic only |
Watchdog | systemd user timer, daily | By default, it needs only the case file and the clock |
Runtime sidecar | Private Amazon Bedrock AgentCore Runtime endpoint in eu-central-1 | Extracts and explains text sent by the PWA demo route |
Office lookup | Web Search Plus MCP over stdio | Identifiers stripped first |
The local workflow does not depend on the Runtime sidecar. A local PWA exposes a separate "Run on AgentCore" button. Its demo route sends one fixed, invented note as text to the private Runtime endpoint. It never sends an uploaded photo or the SQLite case file.
Strands did real work
Papelito is built with Strands Agents, the open-source SDK from AWS. Two parts of the SDK mattered to this implementation.
The
@tool decorator turns a docstring and a type signature into a tool the model can call, so the tool definitions and the code are the same file. Changing the match_case scoring does not require updating a separate schema.OpenAIModel takes a base_url . Strands defaults to Bedrock when no model is passed, and the official examples show the same class with a custom URL. The Zen gateway uses that interface.Python
from strands.models.openai import OpenAIModelvision = OpenAIModel(client_args={"api_key": key, "base_url": ZEN_URL}, model_id="deepseek-v4-flash-vision-exp",params={"max_tokens": 2500, "temperature": 0})
The models are not Bedrock Claude models. Zen handled the photo and text paths through the OpenAI-compatible gateway. The gateway also needs a per-client session header and its own timeout and retry setup, so switching providers is a small amount of client configuration rather than a bare constructor call. Strands still fit this build because the model class accepts a custom base URL.
Why the photos and case file stay local
Kindergarten paper may contain personal data. Two rules follow.
The photo is sent only for the vision call that transcribes it. The transcription, German source lines, calendar file and reply draft are stored with the case on local disk. Text-model calls can also include the transcription, source lines, relevant case details and approved profile names. Deleting a case removes its related rows from SQLite, vacuums the database, unlinks app-managed photos referenced only by that case, and removes the case's exact
.ics and reply filenames. It never deletes a user-supplied source file outside the app-managed private photo directory. There is no soft delete.A household install has no public upload route and no public URL. The judge demo at https://d3cknd2hkoyhzh.cloudfront.net is a separate build, password-protected, on one Lightsail instance in
eu-central-1 . It is preloaded only with synthetic names, photos and cases, and judges use the supplied synthetic demo photos. No household photo is on AWS. Judge credentials must be supplied through an access-restricted channel after confirming who can view that channel.Those two rules also draw the AgentCore boundary in the next section.
AgentCore: what fits, and what does not
The AgentCore boundary follows one question: which parts of Papelito belong on Runtime, and which do not?
AgentCore Runtime is deployed in
eu-central-1 . The local PWA demo route's preset synthetic note states that the outing is on 2026-09-09 and the 8 euro payment is due on 2026-09-07. A successful invocation returns the extracted card with runtime: agentcore . What follows is why the watchdog is still not on it.What fits. Runtime hosts Papelito's extract-and-explain path behind a private invocation endpoint. The entry point validates the JSON payload, requires a string prompt, then passes the payload to the same extract and explain function used by the local application. The note text comes from the request. It is not hardcoded into the entry point. The same
OpenAIModel with a custom base URL runs there, and the gateway key goes into AgentCore Identity as an API-key credential.Python
from bedrock_agentcore.runtime import BedrockAgentCoreAppapp = BedrockAgentCoreApp()@app.entrypointdef invoke(payload, context=None):if not isinstance(payload, dict):return {"error": "payload must be a JSON object"}if not isinstance(payload.get("prompt"), str):return {"error": "prompt must be a string"}from papelito.runtime import extract_and_explainreturn extract_and_explain(payload)if __name__ == "__main__":app.run()
The on-demand work maps onto that. Extract the actions, explain the card. Each is a request with an answer. Runtime accepts note text in the invocation payload. In the recorded live call, the local PWA sends a preset, invented German note to the private endpoint with IAM SigV4. The returned card includes the outing on 2026-09-09 and the 8 euro payment due on 2026-09-07. Dead wait time is trimmed. This route sends no photo at all. That differs from the normal vision path, which does send a photo to the external vision provider for transcription.
What does not fit. The watchdog. Three reasons, and none of them is that AgentCore is bad.
Runtime has no scheduler of its own. Scheduling it would add EventBridge Scheduler or another service, IAM work and retries to replace a two-line systemd timer.
Each session is an isolated microVM with ephemeral disk. The watchdog's whole job is to open
data/papelito.db , find the cases due in two days, and write a due flag back. On Runtime the case state would have to live in durable cloud storage instead of on the local disk. The photos would not have to move with it, but the case file leaving the local machine already changes the rule from the previous section, and the product becomes a different product.The local machine already has the case file and the clock. By default, its daily timer does not need the network. The README says this plainly, and so does this post.
The plan through judging
Judging runs from 15 September to 8 October 2026. Through that window judges get a password-protected demo at https://d3cknd2hkoyhzh.cloudfront.net . It is the same FastAPI app, SQLite case file and daily systemd timer, on a single Lightsail instance in
eu-central-1 behind a Lightsail distribution with no cache. It is preloaded only with synthetic names, photos and cases, and judges use the supplied synthetic demo photos. Judge credentials must be supplied through an access-restricted channel after confirming who can view that channel.That build is the hosted judge sandbox. It has AgentCore disabled and carries no AWS credentials. The Runtime sidecar is separate and stays live for extract and explain. The video was prepared privately and will accompany the submission. It shows one live PWA call to the Runtime endpoint, followed by the architecture diagram. No AWS console appears in the cut.
Household deployments stay local. Web page, timer, case file and photos remain on the parent's machine. The watchdog stays on systemd everywhere, demo included.
The repository is private until submission, when it will be released under MIT at https://github.com/robbyczgw-cla/papelito . The only pre-existing component is Web Search Plus MCP, published before the hackathon. Everything else was written in the submission period with help from AI coding assistants, as disclosed in the submission.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article