From 3661b0e2ad85edd8a71ddcd33d973c4024d867c8 Mon Sep 17 00:00:00 2001 From: Kenneth Kouot <139852202+maketempest@users.noreply.github.com> Date: Thu, 14 May 2026 03:27:44 -0700 Subject: [PATCH] docs(skill): clarify signal payload vs ctx.input input channels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A type:user agent gets input through two channels, and the skill led with "prefer ctx.input over prompt scraping" — true for inputFrom handoffs, but misleading for the common case of a job triggered by a signal with no upstream producer. There, the payload arrives in the `prompt` string and `ctx.input` is empty; an agent following the old guidance guesses a ctx.input key and silently gets nothing back. Add a "which channel?" decision callout at the top of Structured Input Handling, scope the ctx.input intro to inputFrom, and fix the capability table row so it no longer implies ctx.input carries the signal payload. Docs only — no SDK version bump. ## Progress - Task: Workspace-chat mutation-awareness fixes (from a self-modification chat review) - Decisions: Kept the edit to SKILL.md only; left version pinning and the friday-studio re-vendor for a later release. - Key Learnings: The skill is vendored into friday-studio via scripts/sync-sdk-skill.ts at a pinned tag — this branch reaches friday-studio only after release + version bump + re-vendor, so it does not need a coordinated cross-repo change. - Files: packages/python/skills/writing-friday-python-agents/SKILL.md --- .../writing-friday-python-agents/SKILL.md | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/packages/python/skills/writing-friday-python-agents/SKILL.md b/packages/python/skills/writing-friday-python-agents/SKILL.md index 483acd4..e7bee81 100644 --- a/packages/python/skills/writing-friday-python-agents/SKILL.md +++ b/packages/python/skills/writing-friday-python-agents/SKILL.md @@ -56,16 +56,16 @@ Three things are non-negotiable: All capabilities live on `AgentContext` and are always initialized. They may be stubs in test contexts, but never `None`. -| Capability | Access | What it does | -| ----------- | ------------- | --------------------------------------------------------- | -| LLM | `ctx.llm` | Generate text or structured objects via host LLM registry | -| HTTP | `ctx.http` | Make outbound HTTP requests (TLS handled by host) | -| MCP Tools | `ctx.tools` | Call MCP server tools (GitHub, Jira, databases, etc.) | -| Input | `ctx.input` | Read structured action input / `inputFrom` artifact refs | -| Streaming | `ctx.stream` | Emit progress/intent events to the UI | -| Environment | `ctx.env` | Read environment variables (API keys, config) | -| Config | `ctx.config` | Agent-specific configuration from workspace | -| Session | `ctx.session` | Session metadata (id, workspace_id, user_id, datetime) | +| Capability | Access | What it does | +| ----------- | ------------- | --------------------------------------------------------------------------------- | +| LLM | `ctx.llm` | Generate text or structured objects via host LLM registry | +| HTTP | `ctx.http` | Make outbound HTTP requests (TLS handled by host) | +| MCP Tools | `ctx.tools` | Call MCP server tools (GitHub, Jira, databases, etc.) | +| Input | `ctx.input` | Read `inputFrom` upstream-step docs (NOT the signal payload — that's in `prompt`) | +| Streaming | `ctx.stream` | Emit progress/intent events to the UI | +| Environment | `ctx.env` | Read environment variables (API keys, config) | +| Config | `ctx.config` | Agent-specific configuration from workspace | +| Session | `ctx.session` | Session metadata (id, workspace_id, user_id, datetime) | ### ctx.llm — LLM Generation @@ -229,10 +229,25 @@ Emit progress _before_ expensive operations so the UI shows what's happening. ## Structured Input Handling +A `type: user` agent receives input through one of two channels. Pick by how +the job is wired, not by preference: + +- **Signal payload** — the fields the job's trigger signal was fired with, + plus any `{{inputs.}}` the FSM action interpolated. These arrive in + the **`prompt`** string. Parse them with `parse_input(prompt)`. `ctx.input` + does NOT carry the signal payload — a job triggered by a signal with no + upstream producer has an empty `ctx.input`. +- **Upstream step output** — a prior FSM step's `outputTo` document, wired + into this action via `inputFrom`. These arrive in **`ctx.input`**, keyed by + the producing document's id. Use `ctx.input.get("doc-id")`. + +If you guessed a key for `ctx.input.get(...)` and got nothing back, you almost +certainly wanted the signal payload — read `prompt` with `parse_input` instead. + ### ctx.input — Runtime-provided action input -For workspace jobs, prefer `ctx.input` over prompt scraping when consuming -upstream `inputFrom` data. Producers may compact bulky outputs into summary + +When the action declares `inputFrom`, prefer `ctx.input` over prompt scraping +to consume that upstream data. Producers may compact bulky outputs into summary + artifact refs; downstream Python agents should dereference those refs through host capabilities, not ask the producer to inline large payloads.