PawPost Agent
Inspiration
I kept seeing Facebook posts about dogs in high-intake animal shelters across Texas. Sometimes I would return later and learn that the dog had been adopted or pulled by a rescue. Other times, the update said the dog had been euthanized.
I kept wondering whether the outcome might have been different if more people had seen and shared the original post.
Shelter employees and rescue volunteers are not short on compassion. They are short on time. They are feeding animals, cleaning kennels, coordinating fosters, arranging transportation, answering messages, and responding to emergencies. Creating and editing a different video for every animal becomes another job on top of the work that only a person can do.
That is why I originally built PawPost, a web application that turns an animal's information and photos into an adoption video and platform-specific social media captions.
From a Tool to an Agent
The original PawPost workflow required a person for every listing. A shelter worker or volunteer would import an animal, review the information, choose photos, generate the content, and start the render.
My first goal was to make each of those steps faster. But I eventually realized that I was still asking an overwhelmed person to repeat the same workflow for every animal.
Reducing the number of clicks was not enough.
I wanted PawPost to work through a shelter's entire posting queue in the background and involve a person only when human judgment was genuinely needed. That led me to build PawPost Agent with the Strands Agents SDK.
Nobody needs to keep PawPost Agent open. That is the point.
What It Does
PawPost Agent takes a public animal listing and manages the content-production workflow:
- It imports the animal's available information and photos.
- It determines whether a public adoption post is appropriate.
- It examines the actual images and rejects logos, text cards, duplicates, and unusable photos.
- It selects and orders the strongest photos for a vertical video.
- It generates narration and captions for Facebook, Instagram, and TikTok.
- It verifies that the spoken narration fits the renderer's limits.
- It pauses for human approval before consuming a render slot.
- After approval, it resumes the exact paused action and produces the video.
If an animal requires human review, that animal is set aside without blocking the rest of the queue.
How I Built It
PawPost Agent is a TypeScript application built with the Strands Agents SDK. It operates PawPost through its public HTTP API rather than connecting directly to its database or internal infrastructure.
The agent has 12 purpose-built tools for importing listings, creating drafts, offering and selecting photos, generating and editing content, reviewing narration, starting and monitoring renders, escalating cases, and recording decisions.
I designed the system around what I call a judgment boundary.
Deterministic tools handle the predictable work. The agent receives discretion over only four decisions:
- Post or escalate: Is a public adoption post appropriate?
- Choose photos: Which images show the animal clearly, and in what order?
- Review narration: Will the generated script still fit after abbreviations are expanded for speech?
- Route failures: Should a failed action be retried, delayed, skipped, or sent to a person?
This keeps the system autonomous without giving the model unnecessary control over mechanical operations.
Every meaningful judgment is written to an append-only decision log with the choice, reason, alternatives, and relevant facts. A local dashboard displays the queue, completed work, escalations, and pending approval requests.
Human-in-the-Loop Design
Rendering is an outward-facing, rate-limited action, so the agent cannot perform it without approval.
The Strands Human-in-the-Loop intervention interrupts the queue_video tool call. PawPost Agent saves a snapshot of the session and exits. A shelter worker can approve or deny the request later from the dashboard or command line, even after the original process has stopped.
When approved, Strands restores the snapshot and executes the exact tool call that was paused. The agent does not import the listing again, create duplicate resources, or ask the model to reconsider the action.
This lets the agent run quietly in the background while keeping a person in control of the consequential step.
Challenges I Faced
Defining Where the Agent Should Have Control
The biggest design challenge was distinguishing agentic judgment from ordinary automation.
Importing a listing or uploading a photo does not require an AI agent. Interpreting shelter language, comparing images, evaluating generated narration, and deciding how to respond to failures does.
Limiting the agent to four judgment areas made its behavior more predictable, explainable, and testable.
Learning From a Bad Decision
During a live run, an early version escalated a dog because her listing included an imminent euthanasia deadline. Technically, the agent followed its instructions, but the behavior was exactly backward: the animal with the least time was sent into the slowest path.
I changed the judgment boundary so urgency is not automatically treated as a reason to stop. The agent now defaults to continuing when a shelter has already published the animal, while accurately including deadlines, medical needs, and behavioral notes in the content.
Only cases such as rescue-only restrictions or insufficient information require escalation.
Making Pauses Survive Restarts
A normal approval callback disappears when its process exits. I needed a shelter worker to be able to answer later without keeping the original process alive.
Strands snapshots solved that problem, but restoring the conversation was only part of the solution. I also had to rehydrate the local run context so the resumed tool could still access the correct draft, photos, and generated content.
Preventing Scripts From Failing During Rendering
PawPost checks narration length after normalizing it for speech. Abbreviations become longer when spoken. For example, 12 lbs becomes twelve pounds.
A script can therefore pass its written limit and still be rejected by the renderer. The agent reviews both lengths and can remove the least distinctive material while preserving the hook, important facts, and call to action.
Working With Real Shelter Websites
Many shelter list pages load their animal grids with client-side JavaScript. A basic text reader sees only the filter interface or a loading indicator.
Individual detail pages work end to end, but automatic discovery does not yet support every shelter platform. Supporting more platforms will require either platform-specific data integrations or a controlled browser-based discovery layer.
What I Learned
I learned that adding an LLM to a pipeline does not automatically make it an agent.
A useful agent needs meaningful choices, tools that constrain its actions, persistent state, observable decisions, and clear points where control returns to a person.
I also learned that autonomy works best when its limits are explicit. PawPost Agent does not replace shelter workers' judgment. It handles repetitive production work, documents its decisions, and requests attention only when that judgment matters.
The complete workflow has been verified against a live shelter listing:
- Importing the animal
- Visually selecting and ordering photos
- Generating content
- Reviewing the narration
- Interrupting before rendering
- Receiving approval from a separate process
- Restoring the paused session
- Rendering and returning a playable video
The project includes 190 automated tests, including 11 tests that exercise the actual Strands interrupt-and-resume path.
What's Next
My next priorities are:
- Expanding automatic discovery across more shelter platforms
- Optimizing FFmpeg rendering costs
- Testing more complex multi-photo listings
- Making deployment easier for shelters and rescue organizations
PawPost Agent cannot guarantee that an animal will be adopted. What it can do is remove much of the repetitive work required to tell that animal's story, giving more animals a chance to be seen while shelter workers remain focused on their care.## Inspiration
Log in or sign up for Devpost to join the conversation.