8000 feat(automations): ask the model, use an assistant tool, ask the agent by adeelahmad · Pull Request #438 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content

feat(automations): ask the model, use an assistant tool, ask the agent - #438

Merged
adeelahmad merged 1 commit into
mainfrom
claude/project-thread-mwk71t
Oct 15, 2026
Merged

adeelahmad merged 1 commit into
mainfrom
claude/project-thread-mwk71t

Conversation

@adeelahmad
Copy link
Copy Markdown
Owner

Requested by Adeel · project thread

Description

Before: automations could only log a line or send a message; nothing let an automation use the model or the assistant's tools.

After: the AI group of actions (workflow studio M7):

  • ask_model: asks the model a prompt (optional system, model); with json_schema the reply is that object, so later nodes read {{ steps.n3.date }}.
  • call_tool: calls one of the assistant's tools with args and passes on its result, summary and any approvals it made.
  • ask_agent: hands what happened (about, by default {{ event }}) to the assistant's tool loop with instructions, limited to some tools if given, for up to max_steps rounds (6, at most 12). The exchange is saved as a conversation of the person's, titled ": ", so they can open it and approve what it proposed. Output {answer, chat, approvals, steps}.

All three are effect read, because the Toolbox asks for every change itself. While an automation runs, nobody is reading along, so its Toolbox (actions_ai.Box):

  • Turns notes into approvals too. In chat, the assistant writes notes at once.
  • Treats anything that could carry data out of Lens as wary, whatever the run read.
  • Leaves out the namespace assistant's remember.

It acts as automation:<id> with the person's permissions inside the automation's namespaces, using the person's extensions and no server tools. Its approvals belong to the person, so they show in GET /api/v1/approvals, and carry origin: {automation, run, node}.

Prompts: params marked "format": "prompt" are rendered with actions.render_prompt. Before the model sees them, it marks two things as data (untrusted.wrap): each activity's lens.untrusted fields, and everything earlier steps passed on. ask_agent passes the activity the same way. Model calls run in the run's ledger scope and stop once a budget they count for is used up (budgets.used_up).

Motivation and Context

Workflow studio, module M7 (plan: /mnt/project-files/workflow-studio/plan.md §5 M7), PR 2 of 5. #433 added notify; web, Lens work and asset actions follow.

Choices taken (reversible):

  • Every change an automation's agent makes waits, notes included. The brief says the agent's tools "ask for themselves". The chat assistant writes notes at once and runs outbound tools freely when it read nothing from outside. With nobody reading along, both now ask: ai_tools.approve carries out approved write_note / update_note as the approving person.
  • Toolbox account and origin. user is the automation identity (the by), and account is the person. Approvals, extensions, the timeline view and timeline marks use account. Chat behaviour is unchanged (account defaults to user["id"]).
  • Budgets. budgets.used_up(db, refs) checks the run's scope, its namespaces and automation:<id>. The automation ref counts once M6 adds it to budgets.REF.
  • The prompt convention (format: prompt, render_prompt) was sent to the M6 thread for the engine to call.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change; ! in the title)

Checklist:

  • The title is a Conventional Commit.
  • My code follows the code style of this project (ruff, ruff format, mypy clean locally).
  • I added or updated tests. tests/api/test_actions_ai.py covers:
    • catalog and risk
    • ask_model: text, JSON, dry run, no model, budget refusal
    • call_tool: read tools, approvals as the person with origin, notes approved and written, the person's permissions, namespaces
    • ask_agent: saved chat, approvals, limited tools, max steps, dry run, a model without tools
    • the automation Toolbox being wary
    • render_prompt marking outside text
  • My change requires documentation updates, and I have updated docs/ accordingly (docs/automations.md Actions rows and "The model and the agent", docs/assistant.md Approvals).
  • Users need more than the title: n/a, people reach these actions once the engine (M6) runs automations.

Done questions (AGENTS.md)

  • Goal: the AI group of M7; merged on green CI.
  • Agents: the actions are in actions.catalog() (M6 serves it to the API, MCP and the assistant).
  • Zero setup: they use the model already set up.
  • Fewest clicks: defaults filled (about = the event, max_steps 6, the person's usual tools).
  • Configurable: n/a, no new setting.
  • Light: no new dependency; model calls only when an automation uses these actions.
  • Private and secure: every change is the person's approval, outbound tools ask first, and outside text reaches the model marked. P-INJECTION-EGRESS was extended in the threat model (md, yaml, json).
  • Cost: calls run in the run's ledger scope and stop at a used-up budget.
  • User decides: nothing changes without the person's approval; existing chat behaviour is unchanged.
  • Upgrades: approvals gain an optional origin field; no change to stored data.
  • Honest: docs label it built; the engine and the rest of the studio stay planned.
  • Tests and docs updated; no API change, so no OpenAPI regeneration.
  • Open standards; no new dependency.
  • Refine later is written in docs/automations.md:
    • per-node model picks
    • streaming agent steps into the run log
    • memory for automations
    • approving from the chat app
    • the automation's own budget

🤖 Generated with Claude Code

https://claude.ai/code/session_01CyjR2zEfmTXBewKAx9Taw5


Generated by Claude Code

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CyjR2zEfmTXBewKAx9Taw5
@adeelahmad
adeelahmad merged commit 465820f into main Oct 15, 2026
11 checks passed
8000
@adeelahmad
adeelahmad deleted the claude/project-thread-mwk71t branch October 15, 2026 23:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0