Support Togo runtime and flow inputs#24557
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: f2c5d77 | Docs | Datadog PR Page | Give us feedback! |
430449b to
43e744c
Compare
4b754a2 to
489104f
Compare
luisorofino
left a comment
There was a problem hiding this comment.
Thank you!! Every change make sense, but I have a few comments that I am sure will be answered with the next PR of the TUI. Just want to make sure that they are not bugs.
My biggest concern is the one about the inputs of the inspect_endpoint phase.
Approving but looking forward to answers for those comments.
|
|
||
| model_config = ConfigDict(extra="forbid", populate_by_name=True) | ||
| name: str = Field(pattern=VARIABLE_NAME_PATTERN) | ||
| label: str |
There was a problem hiding this comment.
nit: couldn't we have label as optional with default value the input's name, so that we don't have to provide it if we don't care about how "pretty" it looks?
There was a problem hiding this comment.
That label is the one shown in the input above
Not providing it is a pretty bad ux, we should care how "pretty" it looks xD
I can change it but I really think we should force it to make sure it is clear what it is from the ux point of view. Otherwise you are going to be either exposing internal names that might not describe what you want or using huge names everywhere so the label generated looks good.
There was a problem hiding this comment.
Yes, makes sense. I guess my question was more thinking about running the command without the TUI, that was the not "caring for pretty".
But makes sense since its not such a big deal and that way we force in most cases to have that better ux.
| return ResolvedFlow( | ||
| name=flow_name, | ||
| description=fc.description, | ||
| inputs=fc.inputs, |
There was a problem hiding this comment.
question: Currently these two new fields aren't consumed anywhere. I guess that in the next PR they will be used, right?
There was a problem hiding this comment.
Comment generated by Claude for a question I had related to this inputs field:
Related to this and to ResolvedFlow.inputs/convert_inputs: the scalar FlowInput model can't express what inspect_endpoint now consumes, so it's unclear how the TUI would ever produce the flow's very first phase input.
After #24493 (AI-7019), inspect_endpoint no longer reads a single endpoint_url. It reads one runtime variable, inspect_input, whose value is a JSON string that deserializes into a pydantic InspectInput — a list of {name, url} endpoints (a single endpoint is just a one-element list). See inspect_endpoint.py (context.get("inspect_input")) and the InspectInput/EndpointSpec models.
The input layer this PR adds can't produce that value:
FlowInputis scalar-only —string | number | boolean | path— andconvert_inputsreturns a flatdict[str, str]. There is no list/object/repeatable-group type, so there's no way to declare "N(name, url)endpoints" and haveconvert_inputsassemble them into theinspect_inputJSON blob the phase requires.- The tests confirm the gap: every
inspect_endpointtest hand-builds{"inspect_input": json.dumps({"endpoints": [...]})}via_inspect_input_varand injects it directly asruntime_variables— none route throughconvert_inputs. The flow YAML doesn't declare aninputs:block yet either.
So how is the TUI meant to wire endpoints into inspect_input? As the model stands the only options are both unsatisfying: (1) declare a single string input named inspect_input and make the user paste raw JSON, throwing away the typed-input UX; or (2) extend FlowInput with a structured/repeatable type plus a mapping from that group to the inspect_input variable — neither of which exists here.
There was a problem hiding this comment.
yes, they are consumed by the tui.
A json is a string that is parsed into a dict. Not sure why we couldn't be able to provide the input as a string?
This comment
(1) declare a single string input named inspect_input and make the user paste raw JSON, throwing away the typed-input UX;
completely ignores the fact that the user needs to provide this when calling the tool anyway. The user is not "using the typed ux" when providing the list of inputs. We will never ask an user to "build your own code calling this class with this to run a flow". It was always supposed to be a json. If this is an issue then we should rethink the multiple endpoint input to not be a json right? Even without the tui... how was the user supposed to provide this input in a raw cli if not as a json string?
If you want it be a nice json.. then given a path. Say, hey this is the "input config" input, which is a path, read the path and load the json from the file.
There was a problem hiding this comment.
Got it. Makes sense. It's true that there is probably not a better solution rather than just providing the raw json str as input. Sorry for my confusion!
There was a problem hiding this comment.
I would not be surprised if a tool asked me for a file here though. I.e. we probably modify this and have either a single endpoint or multiple endpoints, and if we have multiple endpoints provide a json configuration file. The phase could then read any of those and build the input from that.
| assert tool._process_factory is sentinel_process_factory | ||
|
|
||
|
|
||
| def test_build_runtime_propagates_scope_to_spawn_tool(file_registry): |
There was a problem hiding this comment.
nit: I think we should test that we propagate scope to ToolRegistry, not to that specific spawn tool. Because if we leave it like this, this is also testing that ToolRegistry propagates scope to the tool, but that behavior shouldnt be tested here.
Another smell is: why only spawn_subagent tool, and not spawn_identical_subagents??
There was a problem hiding this comment.
Very likely because when I built this spanw_subagent existed but not the identical subagents and never rebuilt these tests. Will include that.
Because if we leave it like this, this is also testing that ToolRegistry propagates scope to the tool, but that behavior shouldn't be tested here.
I am not sure I understand this part. Do you mean that this shouldn't be in this test_build file or that it should not be tested? We are testing that scoped is propagated all the way doing from the build_runtime. Creating the build runtime and ensuring that the scope is in the tools that will need it is the proper test to build right? What would be your proposal?
There was a problem hiding this comment.
Updated. The AgentRuntimeFactory test now verifies that the complete context, including scope, is passed to ToolRegistry.from_names() without inspecting a concrete tool. ToolRegistry has separate parameterized coverage for both spawn_subagent and spawn_identical_subagents, verifying that each receives the parent scope, agent config, and process factory. This keeps each test at the boundary owned by that component.
489104f to
f2c5d77
Compare
Validation ReportAll 21 validations passed. Show details
|

What does this PR do?
Adds the reusable runtime and configuration support needed by interactive Togo clients: asynchronous orchestrator execution, phase-scoped callbacks across agents and goal checks, improved failure reporting, and typed launch-input metadata propagated through the distributed configuration engine.
Motivation
The Togo TUI runs inside Textual's event loop and needs every callback attributed to the correct phase, including concurrent phases. It also needs descriptions and typed launch inputs from the configuration engine without restoring the removed monolithic flow configuration path.
Review checklist (to be filled by reviewers)
qa/requiredif this PR needs QA validation, orqa/skip-qaif it does not. Exactly one of the two is required.backport/<branch-name>label to the PR and it will automatically open a backport PR once it is merged