mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +00:00
133 lines
6.4 KiB
TypeScript
133 lines
6.4 KiB
TypeScript
'use client'
|
|
|
|
import { YStack } from '@hanzo/ui'
|
|
import { Action, Actions, Band, Head } from './band'
|
|
import { Caption, Dim, Mono, Plate, Row } from './plate'
|
|
|
|
/**
|
|
* What an agent DOES — the layer between Enso and the company. The page could
|
|
* describe a model and a cloud but not the thing in between them that does the
|
|
* work, and this is that thing.
|
|
*
|
|
* THE LEDE IS AN ORDER, and that is still its job. Enso decides, agents
|
|
* coordinate, Tabs is where they act — the three ranked in one sentence instead
|
|
* of competing as equals. Anything added here has to fit somewhere in that order
|
|
* or it does not belong on this page.
|
|
*
|
|
* THE PICTURE IS ONE TOOL DISPATCH, in the shape the run's own span records it.
|
|
* "Agents with hands" was five words in five pills — use tools, operate
|
|
* software, write code, run workflows, hand off to each other — which is a comma
|
|
* list wearing borders, and the least legible way to render the most concrete
|
|
* thing on the page. A reader skips a list of five verbs. One hand actually
|
|
* moving is the claim.
|
|
*
|
|
* WHERE IT WAS READ: hanzoai/cloud `apps/agents/tools.go`. `dispatchOne` opens a
|
|
* span named `agent.tool <name>` and sets `gen_ai.tool.name`,
|
|
* `gen_ai.tool.call.arguments`, `gen_ai.tool.call.result`,
|
|
* `hanzo.agent.tool_subsystem`, `hanzo.agent.tool_round` and
|
|
* `hanzo.agent.tool_outcome` — whose vocabulary is ok | rejected | error, set on
|
|
* every exit including the happy one, because a status written only on failure
|
|
* cannot tell "succeeded" from "never finished". The rows here are those fields.
|
|
* `post_v1_exec_run` is the tool name that file quotes; `exec` is not typed
|
|
* beside it but FOLLOWS from it, since `toolSubsystem` reads the owner as the
|
|
* second word of `<method>_<subsystem>_<rest>`. The argument keys are `CodeRun`'s
|
|
* own (`apps/exec/exec.go`): `lang` selects the toolchain, `code` is the whole
|
|
* program. The VALUES are a hand-authored sample and the caption says so.
|
|
*
|
|
* NO NUMBER HERE WAS CHOSEN. 8 rounds, 30s a call, 90s a run and 3 agents deep
|
|
* are `maxToolRounds`, `toolCallTimeout`, `toolRunBudget` and `maxAgentDepth` —
|
|
* the loop's own constants, in the same file. They are the whole answer to the
|
|
* question a reader actually has about handing software a credential, so they
|
|
* are drawn rather than reassured about. "The eighth gets no tools" is that
|
|
* file's design too: the last round is offered none, so the loop cannot end in
|
|
* anything but words.
|
|
*
|
|
* "HAND OFF TO EACH OTHER" SURVIVES AS A BOUND, which is the honest form of it.
|
|
* An agent is itself a tool (`agentToolProvider`), so a handoff IS one of these
|
|
* dispatches one level down, and `maxAgentDepth` is what stops A→B→A from
|
|
* starting a fresh round cap and a fresh fee at every level. A separate arrow
|
|
* would have drawn the same fact twice, once without its limit.
|
|
*
|
|
* THE ISOLATION SENTENCE IS CUT, and it was an overclaim rather than merely
|
|
* prose. "Every one of them in an isolated environment" said every hand runs
|
|
* isolated; the sandbox belongs to `exec`, in the family's own words ("run a
|
|
* snippet in a sandbox"), and it is per SESSION — `CodeRun.SessionID` continues
|
|
* an EXISTING sandbox so one run's output file is the next run's input — not per
|
|
* call. `Security` already records the same correction from the other side, plus
|
|
* the harder one: there is no egress policy at all, so network isolation is
|
|
* never ours to claim. The plate says `runs in a sandbox` on the one row that
|
|
* earns it and nowhere else.
|
|
*
|
|
* NOTHING DRAWS AN ARROW. The loop is a real sequence — complete, dispatch,
|
|
* append, complete again — and it is still not drawn as one: what a reader needs
|
|
* is that a hand is attributed, bounded and recorded, and five arrows would sell
|
|
* the mechanism to someone who came to find out whether this is safe. One
|
|
* dispatch, opened.
|
|
*
|
|
* DELIBERATELY ABSENT: latency, a success rate, and how many tools exist. The
|
|
* first two have no committed measurement behind them, and a tool COUNT argues
|
|
* against our own product — /mcp's thesis is that a catalog of hundreds
|
|
* collapses into one tool per subsystem, because a tool list is a prompt.
|
|
*
|
|
* This file used to render a SECOND section after this one, the Hanzo Team
|
|
* block. That is now `./Team`: two claims in one file meant the company layer
|
|
* could only be restyled by editing the agent layer.
|
|
*/
|
|
|
|
/** Attribute names print padded to the widest, as a span viewer would — in mono,
|
|
* NBSP is a full column, so the values start at one x. */
|
|
const lead = (s: string) => s.padEnd(9, '\u00A0')
|
|
|
|
|
|
export default function AgentRuntime() {
|
|
return (
|
|
<Band>
|
|
<Head
|
|
eyebrow="Agent runtime"
|
|
title="Agents with hands."
|
|
lede="Enso decides. Agents coordinate. Tabs gives them somewhere secure to act."
|
|
/>
|
|
|
|
{/* The plate is LEFT-set inside a centred measure. Head centres its own
|
|
grid; a log read down a column of aligned field names cannot be
|
|
centred, so it sits outside that grid rather than fighting it. */}
|
|
<YStack width="max-content" maxW="min(520px, 100%)" mx="auto" mt={28}>
|
|
<Plate>
|
|
<Row lead={lead('tool')}>post_v1_exec_run</Row>
|
|
<Row lead={lead('subsystem')}>
|
|
exec<Dim> · runs in a sandbox</Dim>
|
|
</Row>
|
|
<Row lead={lead('round')}>
|
|
2 of 8<Dim> · the eighth gets no tools</Dim>
|
|
</Row>
|
|
<Row lead={lead('actor')}>
|
|
acme/z<Dim> · billed here</Dim>
|
|
</Row>
|
|
<Row lead={lead('arguments')}>
|
|
{'{"lang":"py","code":"…"}'}
|
|
<Dim> · redacted</Dim>
|
|
</Row>
|
|
<Row lead={lead('result')} verdict="ok">
|
|
returned to the model
|
|
</Row>
|
|
{/* The bounds, under a hairline: they belong to the loop rather than
|
|
to this dispatch, and they are the line a reader weighing an
|
|
autonomous run is looking for. Allowed to wrap — it is a limit
|
|
table, not a log line, so nothing about it is read left to right. */}
|
|
<Mono mt={4} pt={10} borderTopWidth={1} borderColor="$edge" color="var(--text-tertiary)">
|
|
bounds · 30s a call · 90s a run · 3 agents deep
|
|
</Mono>
|
|
</Plate>
|
|
<Caption>one tool dispatch, as the run’s span records it · sample values</Caption>
|
|
</YStack>
|
|
|
|
<Actions>
|
|
<Action href="/tabs" filled>
|
|
Explore Tabs
|
|
</Action>
|
|
<Action href="/agents">Explore agents</Action>
|
|
</Actions>
|
|
</Band>
|
|
)
|
|
}
|