Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 127 additions & 1 deletion apps/agentstack-cli/uv.lock

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions skills/agentstack-wrapper/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,12 @@ Evaluate and document the following:

## Step 2 – Classify the Agent

Read the agent's code and classify it:
Read the agent's code and classify it. This determines the `interaction_mode` value:

| Pattern | Classification | Indicators |
| --------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| **Single-turn** | One request → one response | CLI entrypoint, `argparse` (must be removed), primarily stateless business logic, context persistence still recommended |
| **Multi-turn** | Conversation with memory | Chat loop, message history, session state, memory object |
| interaction_mode | Pattern | Indicators |
| ---------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| **single-turn** | One request → one response | CLI entrypoint, `argparse` (must be removed), primarily stateless business logic, context persistence still recommended |
| **multi-turn** | Conversation with memory | Chat loop, message history, session state, memory object |

This classification determines:

Expand Down Expand Up @@ -255,6 +255,7 @@ When building and testing the wrapper, ensure you avoid these common pitfalls:
- **Never silently remove existing optional auth paths.** If the source agent supported optional tokens/keys, preserve that optional behavior unless an approved behavior change is explicitly documented.
- **Never use Forms for a single free-form follow-up.** Use A2A `input-required` for one-question free text prompts; reserve Forms for structured multi-field input.
- **Never mismatch form field IDs and model fields.** Mismatched IDs cause silent parse failures.
- **Never use `context.session_id`.** The `RunContext` object uses `context.context_id` for session identification.
- **Never guess platform object attributes.** `FormRender` uses `fields` (not `items`), `TextField` uses `label` (not `title`).
- **Never skip null-path handling for forms.** Handle `None` for cancelled or unsubmitted forms.
- **Never use `parse_initial_form(...)` truthiness to route turns in multi-turn agents.** Route by presence/absence of persisted session state from `context.load_history()`.
Expand Down
2 changes: 1 addition & 1 deletion skills/agentstack-wrapper/references/files.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ If the agent needs **text** from non-plaintext files (PDFs, DOCX, XLSX, PPTX, im

When uploaded files are provided via `FileField`, use this required strategy:

1. Determine the file `content_type`.
1. Determine the file `content_type` (MIME type). **Always use the MIME type for identification; do not rely on file extensions.**
2. For plain-text-like types (`text/*`, `text/csv`), attempt direct read first.
3. For document/image types, run extraction: call `create_extraction()` and poll `get_extraction()` until `status == "completed"`.
4. Handle extraction `failed` status explicitly with a clear error.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Use this reference for selecting and implementing Agent Stack platform extension
| --------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **LLM Proxy Service** | Needs platform-provided language model access and credentials | [LLM Proxy Service](https://agentstack.beeai.dev/stable/agent-integration/llm-proxy-service.md) |
| **Forms** | Requires structured, named parameter inputs (not just free text) as initial input or during conversation | [Collect Input with Forms](https://agentstack.beeai.dev/stable/agent-integration/forms.md) |
| **Trajectory** | Emits multi-step reasoning, tool calls, long-running progress, or explicit debugging traces | [Visualize Agent Trajectories](https://agentstack.beeai.dev/stable/agent-integration/trajectory.md) |
| **Trajectory** | Yields multi-step reasoning, tool calls, long-running progress, or explicit debugging traces | [Visualize Agent Trajectories](https://agentstack.beeai.dev/stable/agent-integration/trajectory.md) |
| **Files** | Needs to read image or document files uploaded by the user | [Working with Files](https://agentstack.beeai.dev/stable/agent-integration/files.md) |
| **Error** | Needs to report structured, user-visible failures and stack traces | [Handle Errors](https://agentstack.beeai.dev/stable/agent-integration/error.md) |
| **Settings** | Has configurable behavior (for example, "Thinking Mode") | [Configure Agent Settings](https://agentstack.beeai.dev/stable/agent-integration/agent-settings.md) |
Expand Down
14 changes: 8 additions & 6 deletions skills/agentstack-wrapper/references/trajectory.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Use this reference for trajectory decision rules and implementation.

Use this decision rule:

- **Required:** emit trajectory for meaningful intermediate activity: multi-step execution, loops, tool calls, or progress updates. If the agent has multiple steps, it almost always needs trajectories.
- **Required:** yield trajectory for meaningful intermediate activity: multi-step execution, loops, tool calls, or progress updates. If the agent has multiple steps, it almost always needs trajectories.
- **Required (Logs/Prints):** if the original agent uses logging or `print` statements, these are prime candidates to be converted into trajectory entries.
- **Required (hidden internals):** if internal steps are not directly visible, emit trajectory at visible milestones: start, major phase change, completion, and failure.
- **Required (hidden internals):** if internal steps are not directly visible, yield trajectory at visible milestones: start, major phase change, completion, and failure.
- **Optional:** for simple single-step responders with no meaningful intermediate activity, trajectory may be omitted.
- **Default:** when uncertain, enable trajectory.

Expand All @@ -18,10 +18,12 @@ Trajectory entries are metadata for transparency and observability. They are not

When implementing trajectories, follow the [Trajectory Documentation](https://agentstack.beeai.dev/stable/agent-integration/trajectory.md) and utilize these patterns:

- **`yield`**: Use `yield trajectory.trajectory_metadata(title="", content="")` within the main agent generator to emit progress updates.
- **`context.yield_async() or context.yield_sync()`**: to emit trajectory entries from within nested asynchronous functions or utility methods, yielding an `AgentMessage` with trajectory metadata.
- **`trajectory_metadata`**: Use the `metadata` field of `AgentMessage` constructed via the extension's `trajectory_metadata()` method to provide structured, machine-readable context for each trajectory step.
- **Import**: `from agentstack_sdk.a2a.extensions.services.trajectory import TrajectoryExtensionServer, TrajectoryExtensionSpec`
- **Injection**: `trajectory: Annotated[TrajectoryExtensionServer, TrajectoryExtensionSpec()]` as an agent function parameter.
- **`yield`**: Use `yield trajectory.trajectory_metadata(title="...", content="...")` within the main agent generator to emit progress updates.
- **`group_id` for updates**: Use `yield trajectory.trajectory_metadata(title="...", content="...", group_id="...")` to update an existing step instead of creating a new one.
- **Nested functions**: To emit trajectory entries from within nested asynchronous functions or utility methods where `yield` is not possible, you must pass the `trajectory` object and use `trajectory.trajectory_metadata(...)` but the final result must still be `yield`ed by the main generator.

## Anti-Patterns

- Never use `AgentMessage` with empty text to send trajectory metadata
- Never use `AgentMessage` with empty text to send trajectory metadata.
8 changes: 4 additions & 4 deletions skills/agentstack-wrapper/references/wrapper-entrypoint.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Before writing the code, analyze the original source (docstrings, CLI help, READ

- **Identity**: Set a user-friendly `name` and `version`.
- **Documentation**: Use `documentation_url` pointing to the source.
- **Detail**: Populate `AgentDetail` with `interaction_mode` (Step 2), `tools`, `author` (must be a dictionary, e.g., `{"name": "agentstack"}`), and `programming_language`.
- **Detail**: Populate `AgentDetail` with `interaction_mode` (Step 2; must be either `"multi-turn"` or `"single-turn"`), `tools`, `author` (must be a dictionary, e.g., `{"name": "agentstack"}`), and `programming_language`.
- **Skills**: Define `AgentSkill` entries with `id`, `name`, `description`, `tags`, and `examples`.
- **Function Docstring**: The wrapper function's docstring should be a concise summary shown in registries.
- **Extensions**: Identify if the agent needs optional platform capabilities (Step 8) like Citations, Secrets, or Trajectory.
Expand All @@ -34,7 +34,7 @@ Before writing the code, analyze the original source (docstrings, CLI help, READ
| `yield AgentArtifact(...)` / `ArtifactChunk` | Return files, documents, or chunks of structured content back to the caller |
| `yield AuthRequired(...)` | Pause execution to request an OAuth or platform authentication token |
| `Metadata(...)` | Attach extension metadata (e.g., Citations, Canvas references) to an `AgentMessage` |
| `emit trajectory output` | Surface meaningful intermediate logs/progress separately from final user-facing response |
| `yield trajectory.trajectory_metadata(...)` | Surface meaningful intermediate logs/progress separately from final user-facing response |
| `server.run(host, port)` | Starts the HTTP server |

## Implementation: Conditional Workflows
Expand All @@ -47,7 +47,7 @@ Based on the classification in Step 2, follow exactly ONE of these workflows:
- [ ] Extract user message with `get_message_text(input)`
- [ ] Only call `context.load_history()` if continuity is intentionally required
- [ ] Pass necessary inputs (from forms or text) to original agent logic
- [ ] Emit trajectory for meaningful intermediate activity (same rule as all agents)
- [ ] Yield trajectory for meaningful intermediate activity (same rule as all agents)
- [ ] Yield the final response via `AgentMessage(text=result)`
- [ ] Persist both input and response via `context.store()`
```
Expand All @@ -58,7 +58,7 @@ Based on the classification in Step 2, follow exactly ONE of these workflows:
- [ ] Store input: Save incoming user message immediately with `await context.store(input)`
- [ ] Load history: Retrieve past conversation via `[msg async for msg in context.load_history() if isinstance(msg, Message)]`
- [ ] Execute agent: Pass the filtered history to the original agent logic
- [ ] Emit trajectory for meaningful intermediate activity (same rule as all agents)
- [ ] Yield trajectory for meaningful intermediate activity (same rule as all agents)
- [ ] Yield response: Return final answering chunks with `yield AgentMessage(text=...)`
- [ ] Store response: Save the final response with `await context.store(response)`
```
Expand Down