DEV Community

Hagicode
Hagicode

Posted on • Originally published at docs.hagicode.com

How to Use last30days for AI Research Based on Social Networks

How to Use last30days for AI Research Based on Social Networks

Every day on social networks, people express themselves: posting, voting, arguing, unsubscribing, migrating. These scattered voices on Reddit, X, YouTube comments, TikTok, Hacker News, and Polymarket are just noise when viewed individually, but together they form a fairly authentic slice of public opinion. The only problem is—no one wants to manually browse through thirty days of posts across eight platforms just to reach a research conclusion.

That's what the last30days skill was built for. It pulls together the last thirty days of content from these channels for you and synthesizes it by topic. The preset task layer then turns "calling last30days" from a command that requires memorizing parameters into a ready-to-run form.

This article isn't about how useful last30days itself is. Rather, it's about how HagiCode uses the preset task orchestration mechanism to solidly deliver "one skill, four research postures." After all, a skill is a capability, and a preset is the glue that turns capabilities into products.

Background: What Preset Really Saves Is That Sentence Said Over and Over

The preset task system originally bound a skill at the preset level. That is, one preset corresponded to one skill, with a relatively single way of calling it. But in reality, the same capability often needs to be used in different postures—with last30days, sometimes you want to do general research, sometimes you want competitive comparison, and sometimes you only want to analyze prompt style for a specific product.

Hard-coding these different usage patterns into one interaction flow makes the interface increasingly messy; splitting them into four independent skills duplicates work. So the design took a middle step: allow binding skills at the command level. One preset hangs multiple commands, each command self-describing which skill it calls and with what parameters; the preset-level requirements then serve as an authoritative list declaring which skills this preset depends on as a whole.

This way, interface stays interface, execution stays execution. Who wants to mix interface styles with execution logic anyway.

One Skill, Four Modes

The last30days preset is the exemplar of this paradigm: one skill, four commands. Four commands correspond to four research postures:

  • general (broad research): Give a query and let last30days pull relevant discussions from each platform over the last thirty days and synthesize a conclusion.
  • comparison: Explicitly specify the objects to compare, letting the skill organize material around "who's better/who's worse/their respective pain points."
  • competitors: Focus on a product's competitive ecosystem, calling last30days's built-in --competitors flag.
  • prompting (prompt style): Focus on how people actually use it and ask questions, oriented toward usage and mental models.

All four commands declare "skill": "last30days" in commands.json, but each has a different prelude (parameters and prompts). In the frontend drawer, users select a mode, write a query, and check target repositories; as for which command gets assembled behind the scenes, the preset decides that itself. Users don't need to memorize parameters or know about flags like --competitors.

Two Data Layers: commands.json and task-preset.json

Two files in the preset package share responsibilities quite cleanly:

  • commands.json: Describes "what commands exist and what each command looks like." Each command comes with a skill field explaining which skill it calls, plus its own prelude template explaining how to assemble this command into a single-line instruction. This is command-level self-description.
  • task-preset.json: Describes "what this preset needs overall." It holds requirements (the skill dependency list), inputs definitions, inputBindings, and metadata like selectionMode. This is the preset-level authoritative list.

The boundaries between the two layers are quite clear: commands are responsible for saying "I need this skill," and the preset is responsible for saying "which skills my preset allows." If a command declares a skill but it's not in the preset's requirements, validation fails with diagnostic command-skill-not-in-requirements. This explicit failure is much better than silent degradation.

Single-Line Injection: /{skill} {prelude}

What actually connects the skill into the execution flow is an unassuming little mechanism: single-line injection.

PresetTaskCatalogProvider has a method called CombineCommandSkillPrelude. The logic is simple: if a command declares a skill and its rendered prelude line doesn't start with /{skill}, prefix /{skill} onto it. What finally gets handed to the executor is a standalone instruction of the form:

/last30days {commandPrelude}
Enter fullscreen mode Exit fullscreen mode

Then comes the body rendered by user.hbs: mode shaping, query, target repository boundaries, and the constraint of "non-interactive, record assumptions."

Why do this? Because skills like last30days themselves load and run upon "receiving a /{skill} instruction." The preset can't assume the skill will be automatically triggered; it must explicitly feed this instruction in. Just one line, but it's the key that makes the whole chain work.

Five-Stage Technical Chain

Putting all this together, from user clicking submit to conclusion linking back to the repository, there are five stages:

  1. Frontend selection: Users select mode, write query, and check target repositories in CreatePresetTaskDrawer. resolveCommandPreview mirrors the backend assembly logic to show the preview instruction in real time; buildTargetScopeMarkdown groups by read/write and calculates repository boundaries as a markdown segment.
  2. Backend validation: The request lands in SessionsController.PresetTasks.TryResolvePresetTaskRequestAsync. It first validates that inputs/targets/derived keys are on the whitelist, command id is in the catalog, selectionMode is single, then runs PresetTaskRequirementCheckService.CheckAsync: for each skill in requirements, it checks the local skill inventory via LocalSkillCommandAdapter and deduplicates by CacheKey.
  3. Prompt rendering: Renders the corresponding user.hbs according to locale, injecting last30daysMode, last30daysQuery, targetScopeMarkdown, and targetRepositories. user.hbs explicitly forbids AskUserQuestion, requiring the executor to record assumptions rather than ask questions when encountering ambiguity—this is the hard boundary of non-interactive execution.
  4. Skill loading and execution: The executor receives the assembled prompt. /last30days as a standalone instruction comes first, triggering skill loading. Inside the skill, it runs according to its own LAWs: Step 0.45 does keyword-trap pre-check (preventing query from being mistaken for handle/subreddit), Step 0.5/0.55 parses directed channels, Step 0.75 lets the reasoning model generate --plan itself, then runs the Python engine to pull data from Reddit/X/YouTube/TikTok/Instagram/HN/Polymarket/Web, Step 2 supplements with WebSearch, Step 2.5 appends to the raw file, and finally synthesizes a conclusion according to LAWs.
  5. Conclusion linking back: The synthesized conclusion is brought back into the preset context. The read/write boundaries of target repositories rely on the soft constraint of targetScopeMarkdown in the prompt—the preset tells the skill "you can only read these and write those," and the skill follows this boundary during its own execution.

Several Practical Points

  • Non-interactive boundaries must be written into the template. Disabling AskUserQuestion in user.hbs isn't a suggestion, it's a hard constraint. When a preset runs, no one sits in front of the screen answering back-questions, so ambiguities must be digested by "recording assumptions."
  • Pre-set flags that can be preset. The competitors mode writes --competitors directly into the prelude; users don't need to know this flag exists. The meaning of a preset is to hide professional parameters in the right hands.
  • Skill deduplication relies on CacheKey. It doesn't matter if the same skill appears multiple times in requirements; PresetTaskRequirementCheckService deduplicates by CacheKey, so it won't repeatedly check or load.
  • Repository boundaries are soft constraints. Read/write boundaries rely on prompt injection, not sandboxing. This means whether the skill "obeys" depends partly on how well it follows the prompt. This is a realistic compromise.
  • Failures should be explicit, not silent. Missing skills should report requirement check failure, return 400, and provide a "one-click install" entry in the frontend (openSkillGalleryForSkill). Letting users know what's broken and how to fix it is far more responsible than quietly degrading into "can run without skill."
  • Migration should be non-destructive. The evolution from preset-level skill to per-command skill is backward compatible. Old preset-level declarations remain valid; new command-level declarations are additive capabilities, not replacements. Taking too big a step is easy to tear something, so why bother.

Preset task turns one skill into four product forms, not relying on any sophisticated algorithm, but on several contracts with cleanly drawn boundaries: command self-description, preset authoritative list, single-line injection, non-interactive hard constraints, explicit failure. Putting these together, "using last30days for social network research" moves from a command requiring memorized parameters to a feature that runs by filling out a form.

As for what these voices actually prove when gathered together—that's last30days's own job...

Original Article & License

Thanks for reading. If this article helped, consider liking, bookmarking, or sharing it.
This article was created with AI assistance and reviewed by the author before publication.

Top comments (0)