Repository navigation
feat: an agent class's instance is a child that answers requests - #726
Merged
Merged
Conversation
tgockel
force-pushed
the
0003-34-an-agent-class-answers-requests
branch
from
October 27, 2026 19:24
8c57d71 to
ab07ef2
Compare
A subclass of outrig.Agent declares a long-lived child agent. Its docstring is the first part of the child's instructions, and each async def it marks @outrig.agent is a request channel of that name: the method's docstring describes it, its parameters make the request -- none carries None, one its value, several a frozen dataclass <Class><Method>Message the class holds -- and its return annotation is the reply's type. The body is never run or read. Every rule is checked as the class is made, in a module or a submission alike, and a broken one raises TypeError naming the member; @outrig.agent in the body of a class that is not an agent class, or under staticmethod or classmethod, is refused the same way. FooAgent(**inputs, model=...) checks its inputs and returns at once, launching a request child in the background. The child's first round opens as it launches, for getting ready, and await foo.ready() waits for it. A method call checks its arguments, sends the request and returns its handle at once. A request made before the child exists is held on the child's record, made with the instance and taken by the child's kernel when it opens, so it counts against requests-max, cancels and ends like any other, and is sent as the spawn answers. What the launch meets -- an unknown model, a limit, the session closing, a child that cannot be built after its kernel opened -- raises at ready() and at each request, never in the constructor. release(), async with, the session's close, and a finalizer for an instance collected unreleased each end the child and what it launched; a request in flight holds its instance. An instance a child's code made ends with that child, and lets the child's namespace, which holds it, be freed. The host tells the interpreter requests-max in a new limits line, and an instance's readiness in an oriented line. Five events record each instance under its child's subject: agent.instance.started, with a digest of the source that declared the class, .ready, .released, .collected and .handle.collected. Payload gains their variants, with AgentInstanceId and InstanceRelease.
tgockel
force-pushed
the
0003-34-an-agent-class-answers-requests
branch
from
October 27, 2026 20:07
ab07ef2 to
8fb6eac
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A subclass of outrig.Agent declares a long-lived child agent. Its docstring is the first part of the child's instructions, and each async def it marks @outrig.agent is a request channel of that name: the method's docstring describes it, its parameters make the request -- none carries None, one its value, several a frozen dataclass Message the class holds -- and its return annotation is the reply's type. The body is never run or read. Every rule is checked as the class is made, in a module or a submission alike, and a broken one raises TypeError naming the member; @outrig.agent in the body of a class that is not an agent class is refused the same way.
FooAgent(**inputs, model=...) checks its inputs and returns at once, launching a request child in the background. The child's first round opens as it launches, for getting ready, and await foo.ready() waits for it. A method call checks its arguments, sends the request and returns its handle at once. A request made before the child exists is held on the child's record, made with the instance and taken by the child's kernel when it opens, so it counts against requests-max, cancels and ends like any other, and is sent as the spawn answers. What the launch meets -- an unknown model, a limit, the session closing -- raises at ready() and at each request, never in the constructor. release(), async with, the session's close, and a finalizer for an instance collected unreleased each end the child and what it launched; a request in flight holds its instance.
The host tells the interpreter requests-max in a new limits line, and an instance's readiness in an oriented line. Five events record each instance under its child's subject: agent.instance.started, .ready, .released, .collected and .handle.collected. Payload gains their variants, with AgentInstanceId and InstanceRelease.
Summary
What does this change, and why?
Checklist
cargo fmt --all -- --checkpassescargo clippy --workspace --all-targets -- -D warningsis cleancargo test --workspacepassesdoc/updated if behavior changed (mdbook buildstill clean)Notes for reviewers
Anything worth calling out -- tricky bits, follow-ups, or intentionally out-of-scope items.