Observability and Oversight for Academy Agents
As agents act autonomously, the ability to observe what they are doing and intervene
when appropriate becomes a critical capability. academy-dashboard addresses these
challenges in agentic deployments through the following extensions for Academy:
UserAgent: Specialized Academy agents that 1. accepts information from MonitoredAgents
and 2. presents this information over a web based dashboard.MonitoredAgent: Extends academy'sAgentclass to support observability and control features.
Here are some of the supported capabilities:
- Logging: Live log stream from
MonitoredAgentsis presented via theUserAgent - Human-in-the-loop:
MonitoredAgentscan send user prompts to theUserAgentwhere a user can respond over a webpage - Performance Stats: Dashboard presents performance stats collected from
MonitoredAgents - Shutdown:
MonitoredAgents can be terminated from the dashboard provided byUserAgents - Location: Locate your agents on a map
There are two supported modes for using starting a UserAgent:
1) Login with Globus Auth \
2) Click the `[+]` button to launch a new `UserAgent` \
3) Copy the agent UUID and plug this back into your scripts \
Launch locally with: user-agent-launcher,
:>user-agent-launcher
User Agent UUID >>>>
a9337401-3d22-4205-923a-0040bb8d3a7b
* Serving Flask app 'academy_dashboard.user_agent.dashboard'
* Debug mode: off
NOTE: MonitoredAgents need the User Agent's UUID (printed above) to establish a connection.
:> user-agent-launcher -h
usage: user-agent-launcher [-h] [-p PORT] [-r REGISTRATION_FILE] [-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
options:
-h, --help show this help message and exit
-p, --port PORT Port at which the flask service is listening
-r, --registration_file REGISTRATION_FILE
UserAgent registration file
-l, --log_level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
Log levelNOTE: Use
export USER_AGENT_ID=<USER_AGENT_UUID_FROM_ABOVE_STEPS>for examples in the examples directory.
NOTE: This document is in development.
NOTE: The example below is trimmed for brevity. Refer examples for complete code.
from academy_dashboard import MonitoredAgent
from academy_dashboard import UserAgent
class Sleeper(MonitoredAgent):
def __init__(self, user_agent_handle: Handle[UserAgent]) -> None:
super().__init__(user_agent_handle=user_agent_handle)
print('Spinner init done')
@loop
async def cycle(self, shutdown: asyncio.Event) -> None:
"""Log and sleep in loop."""
counter = 0
while not shutdown.is_set():
await asyncio.sleep(2)
logging.info('Sleeper iteration %d', counter)
counter += 1
logging.info('Sleeper exiting!!!! ')
async def main(user_agent_id: UUID) -> None:
async with await Manager.from_exchange_factory(
factory=HttpExchangeFactory(),
executors=ProcessPoolExecutor(max_workers=2),
) as manager:
# 1. Get Handle to UserAgent
agent_id = AgentId(uid=user_agent_id, name='UserAgent')
user_agent_handle = manager.get_handle(agent_id)
# 2. Launch a single agent:
sleeper = await manager.launch(
Sleeper,
kwargs={'user_agent_handle': user_agent_handle}, # <-- Pass handle to UserAgent
)
# 3. Wait for the sleeper agent, which will go on until cancelled
# with a ctrl+c
await manager.wait([sleeper])
logging.info('All done!')
if __name__ == '__main__':
user_agent_id = os.environ['USER_AGENT_ID']
raise SystemExit(asyncio.run(main(UUID(user_agent_id))))
