Skip to content

The Agents pages are Harbor's (0.20.0) - #25

Merged
adamfortuna merged 1 commit into
mainfrom
agents-pages
Nov 14, 2026
Merged

adamfortuna merged 1 commit into
mainfrom
agents-pages

Conversation

@adamfortuna

Copy link
Copy Markdown
Contributor

The Agents pages move into Harbor, the same way the Runs pages did in 0.19.0.

What a site gets

  • Harbor::AgentsController, under Harbor.path:
    • GET /factory/agents with three tabs: the agents, Task routing (?tab=routing) and Shared context (?tab=context)
    • GET /factory/agents/:id, new, POST, edit, PATCH: an agent's page and its form (identity, avatar upload and removal, model alias, workspace, limits, enabled, system prompt, documents as rows on harbor--nested-fields, and tools, default task types and configuration as JSON)
    • GET /factory/agents/:id/avatar: the stored image, private, with an ETag. Not gated by the page switch, because other pages show avatars
    • PATCH /factory/agents/context: the house context, or a shared document by key
  • Harbor::TaskAssignmentsController: PATCH /factory/task_assignments/:task_type gives a declared task type to an agent
  • The menu's Agents entry is the engine's own route (scope: :harbor)
  • harbor_agent_avatar(agent, size:) in every view: an agent's image, or its initial
  • The agents table and the routing table are cards below lg

Where a host plugs in

Partials in the host's app/views/harbor/agents/, rendered when they exist:

Partial Where Locals
_agent_columns_head agents table heading row, twice slot (:first after Agent, :last before Updated)
_agent_columns an agent's row, twice agent, slot
_routing_columns_head routing table heading row, between Task and Agent none
_routing_columns a task type's row task_type, assignment
_show_facts an agent's page, in the facts card after the model alias agent
_form_extras the form's grid, after the description form, agent

Config:

  • config.agent_params: attributes of the host's agent class the form may save. Assigned before Harbor's own fields, so the form's field wins where both set the same thing
  • config.agent_edited: called with (agent, current user) when an agent is saved from the form, before it is checked and saved; never for a save made any other way
  • config.task_assignment_class (Harbor.task_assignment_class): the host's subclass of Harbor::TaskAssignment. compatible_agents(task_type) decides who the routing tab offers and accepts; the new refusal(task_type, agent_key) words the alert for anyone else

Also

  • An agent saved from the form needs a model alias (one without can't run). Agents made in code are not held to it
  • Harbor::AgentSetting.editable_key?(key): the keys the Shared context tab may write
  • harbor_current_user moved from the Runs controller to Harbor::ApplicationController
  • Version 0.20.0, CHANGELOG with an "Upgrading from 0.19" note, README section "Agents pages"

Tests

test/agents_pages_test.rb (47 tests): each page and tab, creating and editing with every validation, the JSON fields (bad JSON keeps what was typed), documents added, edited and removed, the avatar (upload, serving, caching, 404, removal), routing (assign, refuse, unknown task type, a host's class), shared context (house context, a shared document, refused keys), each host partial present and absent, extra permitted params, the save hook, the page switch, the login, and the menu marking Agents on an agent's page and on the routing tab.

Full suite: 600 runs, 0 failures. Rubocop clean.

Not tagged or released.

…, an agent's page, form and avatar

Harbor::AgentsController serves /factory/agents with its Task routing and
Shared context tabs, an agent's page, the form that creates and edits one,
its avatar and PATCH /factory/agents/context;
Harbor::TaskAssignmentsController gives a task type to an agent. The menu's
Agents entry is the engine's own route. A site with no code of its own gets
all of it: identity, avatar upload and removal, model alias, workspace,
limits, the system prompt, documents as rows (harbor--nested-fields), tools,
default tasks and configuration as JSON, routing over the declared task
types, and what every agent is told. The agents and routing tables are cards
on a phone.

A host adds to the pages with partials in its own app/views/harbor/agents/,
rendered when they exist: _agent_columns_head and _agent_columns (its own
columns in the agents table, in two places), _routing_columns_head and
_routing_columns, _show_facts and _form_extras.

What is code is config: agent_params names the host's attributes the form
may save, agent_edited is called when an agent is saved from the form and at
no other time, and task_assignment_class names the host's subclass, whose
compatible_agents decides who a task type is offered to and whose refusal
words the alert for anyone else.

harbor_agent_avatar draws an agent in any view: its image, or its initial.
An agent saved from the form needs a model alias. 0.20.0.
@adamfortuna
adamfortuna merged commit db8cc77 into main Nov 14, 2026
2 checks passed
@adamfortuna
adamfortuna deleted the agents-pages branch November 14, 2026 22:30
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.

1 participant