v29: Per-user config, agent manager enhancements, MCP improvements#30
Conversation
- BaseAgent resolves config: env var > arg > default workflows/testbed.toml - Store resolved config_path as self.config_path for subclasses - Add SIGTERM/SIGQUIT handlers for graceful EXITED reporting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Test Coverage Summary |
There was a problem hiding this comment.
Pull request overview
Adds infrastructure baseline updates to the common agent runtime to support per-user testbed configuration selection and more graceful shutdown behavior.
Changes:
- Resolve testbed config path via
config_patharg,SWF_TESTBED_CONFIG, or defaultworkflows/testbed.toml - Always load the testbed configuration to set the namespace during agent initialization
- Register process signal handlers in
run()to trigger graceful shutdown
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| signal.signal(signal.SIGTERM, signal_handler) | ||
| signal.signal(signal.SIGQUIT, signal_handler) | ||
|
|
There was a problem hiding this comment.
PR description mentions cleaner shutdown on SIGTERM/SIGINT, but this code registers SIGTERM and SIGQUIT. If SIGINT handling is intended (to unify Ctrl+C and SIGTERM behavior/logging), register SIGINT here; otherwise consider updating the PR description/release notes to match the actual signals handled.
| raise KeyboardInterrupt(f"Received {sig_name}") | ||
|
|
||
| signal.signal(signal.SIGTERM, signal_handler) | ||
| signal.signal(signal.SIGQUIT, signal_handler) |
There was a problem hiding this comment.
signal.SIGQUIT is not available on all platforms (notably Windows). Calling signal.signal(signal.SIGQUIT, ...) will raise at runtime where SIGQUIT is undefined, preventing the agent from starting. Consider guarding this registration (e.g., only register SIGQUIT when present) or limiting to signals that exist across supported platforms.
| signal.signal(signal.SIGQUIT, signal_handler) | |
| if hasattr(signal, "SIGQUIT"): | |
| signal.signal(signal.SIGQUIT, signal_handler) |
| if config_path is None: | ||
| env_config = os.getenv('SWF_TESTBED_CONFIG') | ||
| if env_config: | ||
| # Env var is filename, resolve to workflows/ directory | ||
| if not env_config.startswith('workflows/') and '/' not in env_config: |
There was a problem hiding this comment.
config_path used to be effectively optional (when None), but this change now always resolves a default file path and will attempt to load a config even when callers omit config_path. If any existing consumers relied on config_path=None meaning “don’t load config / no namespace”, this becomes a breaking behavior change. Consider preserving the old behavior (only resolve default when explicitly requested), or clearly document the new defaulting behavior (incl. SWF_TESTBED_CONFIG) and treat it as a deliberate breaking change/version bump.
| try: | ||
| config = load_testbed_config(config_path=config_path) | ||
| self.namespace = config.namespace |
There was a problem hiding this comment.
load_testbed_config(config_path=...) is now called unconditionally. If a caller passes an empty string (previously treated as falsy and skipped), Path('') resolves to the current directory and the load will fail with a non-TestbedConfigError (e.g., IsADirectoryError) that won’t be caught/logged by this except. Consider validating config_path (non-empty, points to a file) before calling load_testbed_config, or treating empty string the same as None.
Summary
Infrastructure baseline v29 brings per-user configuration support, agent manager improvements, and MCP enhancements.
Key Changes
SWF_TESTBED_CONFIGenv var) - multiple users can run separate testbed instances with different configurationsget_testbed_status- comprehensive status combining agent manager, namespace, and workflow agentsSee RELEASE_NOTES.md for full details.
🤖 Generated with Claude Code