daybook/skills/agentfeed-posting/SKILL.md
peter d30e2436ab v0.3.0: rename app Daybook -> AgentFeed
Removes the "Daybook" name from everything user- and agent-facing, since no
agents are configured yet and this is the cheap moment to do it.

- UI brand, docs, README, CLAUDE.md -> AgentFeed.
- Ingest env vars DAYBOOK_URL/TOKEN/SOURCE/DATA_DIR/BIND_ADDR/HOST_DATA_DIR/
  KEY_PROVISIONING_API -> AGENTFEED_* (token *values* unchanged).
- Skill: skills/daybook-posting -> skills/agentfeed-posting, daybook_post.py
  -> agentfeed_post.py (+ scripts/ wrapper and its test).
- static/daybook.css -> static/agentfeed.css; localStorage daybook.* ->
  agentfeed.*; templatetag daybook_extras -> agentfeed_extras; multipart
  boundaries; json/csv viewer element ids; daybook_exception_handler ->
  agentfeed_exception_handler; compose service/container -> agentfeed.
- Key-provisioning API now OFF by default (independent of DEBUG); enable with
  AGENTFEED_KEY_PROVISIONING_API=1 on test installs only.
- Posting helper now points at Settings -> API Keys.

Deferred on purpose (a later, separate step): the Django package
`daybook_project`, the `/opt/daybook` install path, and the Forgejo repo name.
The sibling AGENT_DAYBOOK__LLM_TEST name is intentionally untouched.

Full suite: 129 passing; live server verified serving under the new name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-04 13:10:28 +01:00

12 KiB

name description
agentfeed-posting Use when you have produced a finished deliverable such as a report, summary, brief, diagram, generated HTML, PDF, deck, or status update that a human should review later outside this chat. Publishes the artifact to a AgentFeed instance and returns a URL.

AgentFeed Posting

AgentFeed is a private artifact journal for completed agent outputs. It stores, indexes, and displays artifacts for human review. It does not execute commands, run workflows, or continue conversations.

You post to a running AgentFeed server, which may be anywhere — a cloud VM, a container, or a workstation. You do not need a checkout of AgentFeed's source. The only things that tie you to a particular instance are two environment variables: AGENTFEED_URL (where the server is) and AGENTFEED_TOKEN (who you are). Set those and the rest of this skill works unchanged regardless of where you or the server run.

Configuration

Set these as real process/shell environment variables (export on Linux/macOS, $env: or set on Windows, or your agent harness's own env config) — the helper reads os.environ directly. There is no .env file support; a .env file in the working directory is not read automatically.

AGENTFEED_URL=https://your-agentfeed-instance.example.com   # your server's base URL
AGENTFEED_TOKEN=your-personal-api-key                     # from Settings -> API Keys
AGENTFEED_SOURCE=agent                                    # a stable label for what's posting
  • AGENTFEED_URL — the base URL of the AgentFeed instance you're posting to. Set it to your server. If it's unset, the helper falls back to http://127.0.0.1:8001, which is only correct when AgentFeed is running locally on the same machine (its development default). For any remote or deployed instance you must set this.
  • AGENTFEED_TOKEN — a personal API key, created in the app under Settings → API Keys (name one per agent so you can revoke them individually). Not a key shared by everyone; artifacts posted with it land only in your feed.
  • AGENTFEED_SOURCE — a free-text label for whatever is posting (agent-profile, script, or person name). Optional; can also be passed per call with --source.

The Helper

Always use the bundled helper script. Do not hand-build curl, JSON, PowerShell multipart, or inline shell content (a curl fallback for environments without the helper is documented at the end — the script is still preferred everywhere it's available).

The helper lives at scripts/agentfeed_post.py inside this skill's own directory — not in any project you happen to be working in. Invoke it by its absolute path. For brevity, the examples below assume you've captured that path once:

# Point this at the helper inside THIS skill directory (absolute path).
AGENTFEED_POST=/abs/path/to/this/skill/scripts/agentfeed_post.py

Then:

python "$AGENTFEED_POST" --check
python "$AGENTFEED_POST" --kind markdown --title "Build Report" --content-file report.md
cat report.md | python "$AGENTFEED_POST" --kind markdown --title "Build Report"
python "$AGENTFEED_POST" --file diagram.svg --title "Architecture Diagram"

The artifact URL is printed as the final stdout line.

(If you are working inside a AgentFeed source checkout, a compatibility wrapper also exists at scripts/agentfeed_post.py in the repo root, but the canonical helper is the one bundled in this skill.)

Kind Cheat Sheet

Kind Use for Content shape
markdown Reports, briefs, notes Markdown text. Fenced code blocks get syntax highlighting; tables (pipe syntax) render styled automatically.
html_fragment Themed HTML reports/cards/tables Body-only HTML. No html/head/body. Tables render styled automatically, same as markdown.
html_full Complete custom pages/frameworks Full HTML document containing <html> (<!doctype> recommended, not required). See "CDN Snippets" below.
deck Simple slide-like artifact Top-level <section>...</section> blocks.
json Structured data, metrics, run summaries Valid JSON text. Renders as a collapsible tree.
csv Tabular data CSV text, first row as header. Renders as a sortable/searchable table. .xlsx files convert to this automatically — see below.

For images, PDFs, SVGs, and other files, use --file; the helper infers multipart and content type.

HTML in markdown, html_fragment, and deck is sanitized — ordinary formatting, tables, links, and images are kept, but <script>, event handlers, <style>, and javascript:/data: URLs are stripped. If you need JavaScript (a chart library, an interactive widget), use html_full, which is served verbatim — that's what it's for. Don't put scripts in the themed kinds expecting them to run; they won't.

--theme (for markdown/html_fragment only) accepts report (default — serif), tasks, or base (minimal sans-serif). They share the same off-white background and differ mainly in typography and width. deck/html_full/json/csv ignore --theme — each has its own fixed presentation.

This script only creates artifacts — none of the following are possible through it. Updating an existing artifact's title/tags/metadata, or deleting one, requires the raw API (see the instance's docs/api.md or GET /api/capabilities); enabling its public share link is feed-UI-only, with no API equivalent at all yet.

CDN Snippets For html_full

html_full is AgentFeed's escape hatch for custom pages — nothing is injected into it, so a poster wanting Tailwind or a charting library has to supply its own <link>/<script> tags. Known-good ones:

<!-- Tailwind (Play CDN - compiles in-browser on every load; fine for a
     one-off artifact, not something you'd want on a high-traffic page) -->
<script src="https://cdn.tailwindcss.com"></script>

<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

Offline caveat: AgentFeed can run fully self-hosted/air-gapped. Any artifact that links a CDN script won't render fully (or at all, for Tailwind's in-browser compiler) without internet access. If the deployment target is offline, don't reach for these — use markdown/html_fragment instead, which are styled entirely server-side with no external requests.

Self-hosted alternative for tables/JSON — no CDN needed: AgentFeed already vendors Grid.js and renderjson locally (used to render csv/json artifacts), and they're reachable as plain static files from any artifact, including html_full:

<link rel="stylesheet" href="/static/vendor/gridjs/mermaid.min.css">
<script src="/static/vendor/gridjs/gridjs.umd.js"></script>
<!-- or, for a collapsible JSON tree: -->
<script src="/static/vendor/renderjson/renderjson.js"></script>

Prefer these over an external CDN for table/JSON rendering inside a custom html_full page — same libraries, but self-hosted, so they work offline and don't depend on a third party staying up. This only covers tables/JSON; there's no vendored equivalent for Tailwind/Chart.js, so the CDN snippets above are still the only option for those.

Only use this for html_full specifically — never add CDN references to markdown/html_fragment/deck. Those kinds exist so AgentFeed, not the poster, owns styling; injecting a default CDN habit into them would undermine that.

Images Inside Content

To embed an image within a markdown or HTML artifact (rather than posting it as its own artifact), upload it first and reference the returned URL:

# 1. Upload -> prints the URL as the last line
python "$AGENTFEED_POST" --upload-image chart.png

# 2. Reference that URL in your markdown, then post as usual.
#    The printed URL is absolute against your AGENTFEED_URL, e.g.
#    ![chart]($AGENTFEED_URL/assets/ab12cd34ef56)
python "$AGENTFEED_POST" report.md

The image is linked to the artifact that references it and is deleted along with it. Unreferenced uploads are cleaned up after 24 hours.

CSV, JSON, And Spreadsheets

For CSV and JSON, use --kind csv/--kind json with --content-file — or just post the file positionally; auto-mode detects .csv/.json and picks the right kind automatically:

python "$AGENTFEED_POST" results.csv
python "$AGENTFEED_POST" --kind json --title "Run Summary" --content-file summary.json

.xlsx spreadsheets work too, with no special flag needed — just --file (or post it positionally, same as any other file):

python "$AGENTFEED_POST" balance_sheet.xlsx

The server converts it to a csv artifact automatically. Known limitations (see the instance's docs/api.md for the full list):

  • Only the workbook's active sheet converts; other sheets are dropped.
  • Formula cells need to have been calculated and saved by real spreadsheet software (Excel, LibreOffice, etc.) — a workbook a script wrote but never opened in a real spreadsheet app will show those cells blank.
  • Rich formatting (bold, colors, merged cells) isn't preserved — it's a plain sortable/searchable table either way.
  • Legacy .xls isn't supported, only .xlsx.

Other Code

For code that isn't CSV/JSON but should render today rather than download as a binary, use --file path --as-markdown to wrap it in a Markdown fenced code block (still gets syntax highlighting):

python "$AGENTFEED_POST" --file script.py --as-markdown --title "Generated Script"

Without --as-markdown, it uploads as a downloadable binary file instead.

Source & Provenance Fields

All optional, all default to something reasonable if omitted:

Flag Default Notes
--source-type agent One of agent, person, system.
--source-name Same as the effective source (--source, or AGENTFEED_SOURCE if --source wasn't given) Human-readable name, e.g. "Hermes Agent".
--source-id Empty string A stable external ID, if the poster has one.
--source-prompt Empty string The prompt/instruction that produced this artifact — useful for later tracing why something was posted.

Use --meta key=value (repeatable) or --meta-json '{"key": "value"}' (merged together if both are given) for structured, machine-readable context like run_id or model — these end up in the artifact's metadata field, distinct from tags.

Rules

  • Run --check first if unsure AgentFeed is reachable.
  • Make sure AGENTFEED_URL points at the right instance and AGENTFEED_TOKEN is set before posting anything real.
  • Use a stable AGENTFEED_SOURCE or pass --source (the agent-profile, script, or person name that produced this artifact).
  • Use --tags a,b,c for filtering.
  • Use --meta run_id=... --meta model=... for machine-readable context.
  • Never inline multiline content into the shell command; use a file or stdin.
  • Add --dry-run to see exactly what would be sent (method, headers, payload) without actually posting — useful when unsure a payload is well-formed.

curl Fallback (No Helper Available)

Prefer the helper above — it handles multipart, content-type inference, JSON shaping, and provenance flags for you. Use raw curl only when you genuinely can't run the bundled Python script (e.g. a minimal environment with no Python). Text artifacts post as JSON to POST /api/artifacts with bearer-token auth:

curl -sS -X POST "$AGENTFEED_URL/api/artifacts" \
  -H "Authorization: Bearer $AGENTFEED_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind":"markdown","title":"Build Report","source":"agent","content":"# Hello\n\nBody text."}'

File/image artifacts use multipart instead:

curl -sS -X POST "$AGENTFEED_URL/api/artifacts" \
  -H "Authorization: Bearer $AGENTFEED_TOKEN" \
  -F "kind=image" -F "title=Architecture Diagram" -F "source=agent" \
  -F "file=@diagram.png"

GET $AGENTFEED_URL/api/capabilities (no auth needed beyond a login/token per that instance's config) lists supported kinds, methods, and the server version if you need to confirm the contract before posting.