> Discover all available pages from the documentation index: https://mastra.zisheng.pro/ko/llms.txt # AgentController :::실험적 그만큼[`AgentController`](https://mastra.zisheng.pro/ko/reference/agent-controller/agent-controller-class) 기능은 beta 단계이며 beta 상태를 벗어나기 전까지 minor 버전에서 호환성을 깨는 변경이 발생할 수 있습니다. ::: `AgentController`대화형 Agent 애플리케이션을 위한 공유 런타임 호스트입니다. 모드, Model, 스토리지, 작업 공간, Tool 승인, 하위 Agent 및 채널을 조정합니다. 각 사용자 또는 활성 작업은 격리된 작업을 통해 작동합니다.[`Session`](https://mastra.zisheng.pro/ko/reference/agent-controller/session). [마스트라 코드](https://code.mastra.ai)주력 AgentController 구현입니다. 다중 Model 지원, 지속적인 대화, 계획 후 실행 Workflow를 갖춘 터미널 기반 코딩 Agent입니다. 읽다[Building a coding agent](https://mastra.zisheng.pro/ko/guides/guide/coding-agent) for a step-by-step guide. ## AgentController를 사용하는 경우 애플리케이션에 다음이 필요할 때 AgentController를 사용하세요. - 하나의 대화 스레드를 공유하는 다중 Agent 모드(예: 계획 → 구축 → 검토) - UI와 Agent 루프 사이의 제어 계층(Model 전환, 상태 지속성, 스레드 관리) - Human-In-The-Loop 게이팅을 위한 Tool 승인 흐름 및 권한 정책 - 제한된 Tool을 사용하여 집중된 하위 작업을 위임하는 하위 Agent 오케스트레이션 - 각 세션에 대해 격리된 라이브 상태를 포함하여 다시 시작 시 지속 스레드 및 선택된 스레드 설정 이 모든 것을 직접 조립할 수도 있습니다.[Agent class](https://mastra.zisheng.pro/ko/docs/agents/overview), 전체 Agent 루프, Tools, Memory를 노출합니다. AgentController는 Agent가 일회성 endpoint가 아닌 협업자로 동작하는 지속적인 Session을 위해 명확한 기본값을 제공합니다. 완전한 제어 또는 request-response 호출이 필요하면 Agent 클래스를 직접 사용하세요. 주변 runtime을 직접 구축하지 않고 협업 Session Model을 사용하려면 AgentController를 사용하세요. ## 빠른 시작 지지대 만들기[`Agent`](https://mastra.zisheng.pro/ko/reference/agents/agent), storage, and [`Workspace`](https://mastra.zisheng.pro/ko/reference/workspace/workspace-class). Call [`controller.init()`](https://mastra.zisheng.pro/ko/reference/agent-controller/agent-controller-class) once, then use [`controller.createSession()`](https://mastra.zisheng.pro/ko/reference/agent-controller/agent-controller-class) to create a Session. Subscribe with [`session.subscribe()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session) and send work with [`session.sendMessage()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session): ```typescript import { Agent } from '@mastra/core/agent' import { AgentController } from '@mastra/core/agent-controller' import { LocalFilesystem, Workspace } from '@mastra/core/workspace' import { LibSQLStore } from '@mastra/libsql' const agent = new Agent({ id: 'assistant', name: 'Assistant', instructions: 'Help the user plan and complete tasks.', model: 'openai/gpt-5.6-sol', }) const controller = new AgentController({ id: 'assistant-controller', agent, storage: new LibSQLStore({ id: 'agent-controller-storage', url: 'file:./mastra.db', }), workspace: new Workspace({ id: 'assistant-workspace', filesystem: new LocalFilesystem({ basePath: './workspace' }), }), modes: [ { id: 'plan', name: 'Plan', metadata: { default: true }, instructions: 'Reason about the task before making changes.', }, { id: 'build', name: 'Build', instructions: 'Implement the approved plan.', }, ], }) await controller.init() const session = await controller.createSession({ resourceId: 'user-123', }) const unsubscribe = session.subscribe(event => { if (event.type === 'message_update') { console.log(event.message) } }) await session.sendMessage({ content: 'Plan a small TypeScript CLI.' }) unsubscribe() ``` 많은 세션에 동일한 컨트롤러를 사용합니다. 컨트롤러에 현재 세션을 저장하거나 컨트롤러 수준 메시지 방법을 통해 작업을 라우팅하지 마세요. ## 런타임 Model 이해 컨트롤러, 세션 및 스레드의 수명은 다릅니다. - **제어 장치**: 구성 및 런타임 서비스를 위한 공유 호스트입니다. 한 번 초기화하고 다시 사용하세요. - **세션**: 하나의 사용자, 작업 또는 동시 작업 범위에 대한 격리된 라이브 런타임입니다. 활성 모드, Model, 상태, 이벤트 버스, 실행 상태, 권한 부여 및 현재 스레드 바인딩을 소유합니다. - **실**: 메시지와 스레드 설정이 포함된 저장된 대화입니다. 스레드는 스토리지를 구성할 때 컨트롤러 및 프로세스 재생성을 유지할 수 있습니다. 세션은 라이브 상태입니다. 임의[`session.state`](https://mastra.zisheng.pro/ko/reference/agent-controller/session), 권한 부여, 대기 중인 승인, 활성 실행은 프로세스를 다시 생성해도 자동으로 유지되지 않습니다. Mode 및 Mode별 Model 선택을 비롯한 thread 메시지와 선택된 thread 설정은 storage를 통해 유지할 수 있습니다. ## 세션 및 스레드 `createSession()`다음으로 가져오거나 생성합니다.`resourceId` and optional `scope`: ```typescript const webSession = await controller.createSession({ resourceId: 'user-123', scope: 'web', }) const sameWebSession = await controller.createSession({ resourceId: 'user-123', scope: 'web', }) const workerSession = await controller.createSession({ resourceId: 'user-123', scope: 'background-worker', }) console.log(webSession === sameWebSession) // true console.log(webSession === workerSession) // false ``` 범위가 서로 다른 세션에는 별도의 이벤트 버스, 실행 루프, 상태, 모드 및 Model 선택, 현재 스레드 바인딩이 있습니다. 저장된 스레드는 여전히 공유 스레드에 속합니다.`resourceId`. 통과하다`threadId` host가 Session을 정확한 thread에 바인딩해야 할 때 사용합니다. controller는 기존 thread로 전환하거나, 해당 ID의 thread가 없으면 새로 생성합니다. 이 동작은 다음 경우에도 적용됩니다: `createSession()` returns a cached Session: ```typescript const session = await controller.createSession({ resourceId: 'user-123', scope: 'web', threadId: 'support-ticket-42', }) ``` 사용[`session.thread.create()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session) and [`session.thread.switch()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session) to move one live Session between conversations. ## 모드 및 Model 전환 모드는 세션이나 스레드를 교체하지 않고 공유 지원 Agent에서 사용하는 지침과 Tool을 변경합니다. 컨트롤러에서 모드별 Tool 및 가시성을 구성합니다. ```typescript const modes = [ { id: 'plan', name: 'Plan', metadata: { default: true }, instructions: 'Investigate the task and propose a plan.', additionalTools: { searchDocs }, availableTools: ['searchDocs', 'submit_plan'], transitionsTo: 'build', }, { id: 'build', name: 'Build', instructions: 'Implement the approved plan.', }, ] ``` `tools`그리고`additionalTools` 는 Mode별 Tools를 추가하기 위한 상호 배타적인 입력입니다. controller에 공유 기반 Agent가 있으면 어느 입력을 사용하든 해당 Tools가 Agent의 Tools 위에 추가됩니다. 다음을 사용하여 `availableTools` Mode에서 최종적으로 노출되는 Tool 이름을 제한하세요. 권한 거부가 이 allowlist보다 계속 우선합니다. 다음으로 라이브 세션을 전환하세요.[`session.mode.switch()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session). Read the active mode with [`session.mode.get()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session) or [`session.mode.resolve()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session): ```typescript await session.mode.switch({ modeId: 'build' }) console.log(session.mode.get()) // "build" console.log(session.mode.resolve().instructions) ``` 다음을 사용하여 독립적으로 Model 전환[`session.model.switch()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session), then read the active selection with [`session.model.get()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session). Thread 범위의 선택 사항은 Mode별로 저장되며 Session이 해당 Mode로 돌아오면 복원됩니다: ```typescript await session.model.switch({ modelId: 'anthropic/claude-sonnet-4-6', scope: 'thread', }) console.log(session.model.get()) ``` 사용`scope: 'global'` thread 설정에 기록하지 않아야 하는 메모리 내 선택에 사용합니다. ## 스레드 및 상태 관리 다음 사람과의 저장된 대화 목록을 나열합니다.[`session.thread.list()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session): ```typescript const thread = await session.thread.create({ title: 'Release planning' }) const threads = await session.thread.list() await session.thread.switch({ threadId: thread.id }) console.log(threads.length) ``` 사용`session.state` Session과 연결된 구조화된 실시간 상태에 사용합니다. 다음을 사용해 읽으세요: [`session.state.get()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session) and write updates with [`session.state.set()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session). Define `stateSchema` and `initialState` 유효성 검사와 기본값이 필요할 때 controller에서 사용합니다: ```typescript console.log(session.state.get()) await session.state.set({ activeProject: 'docs-site' }) ``` `session.state.get()`스냅샷을 반환합니다.`set()` 업데이트의 유효성을 검사하고 Session 상태에 병합합니다. host가 이 상태를 명시적으로 유지하고 복원하지 않는 한, 실시간 Session 데이터로 취급하세요. ## Tool 승인 및 정지 재개 권한 정책은 Tool을 허용할지, 거부할지 또는 승인을 위해 UI로 보낼지 여부를 결정합니다. 다음을 사용하여 사용자 정의 Tool을 카테고리에 매핑합니다.`toolCategoryResolver` on the controller: ```typescript const controller = new AgentController({ toolCategoryResolver: toolName => { if (toolName === 'delete_project') return 'execute' return null }, }) ``` 다음을 사용하여 카테고리 정책을 구성합니다.[`session.permissions.setForCategory()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session) and tool policies with [`session.permissions.setForTool()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session): ```typescript await session.permissions.setForCategory({ category: 'execute', policy: 'ask', }) await session.permissions.setForTool({ toolName: 'delete_project', policy: 'deny', }) ``` 정책이 다음과 같이 해결되면`ask`, 승인 event를 구독하고 다음을 사용해 사용자의 결정을 반환하세요: [`session.respondToToolApproval()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session): ```typescript session.subscribe(event => { if (event.type === 'tool_approval_required') { session.respondToToolApproval({ toolCallId: event.toolCallId, decision: 'approve', }) } }) ``` 그만큼`always_allow_category` 결정은 현재 실시간 Session의 나머지 기간 동안 해당 Tool category를 허용합니다. Session 권한 부여는 영구적인 process-level 권한이 아닙니다. 다음과 같은 대화형 Tool[`ask_user`](https://mastra.zisheng.pro/ko/reference/tools/ask-user-tool) and [`submit_plan`](https://mastra.zisheng.pro/ko/reference/tools/submit-plan-tool) 대신 재개 가능한 Tool suspensions를 사용하세요. 다음을 사용해 재개합니다: [`session.respondToToolSuspension()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session): ```typescript session.subscribe(event => { if (event.type === 'tool_suspended' && event.toolName === 'ask_user') { void session.respondToToolSuspension({ toolCallId: event.toolCallId, resumeData: 'Use SQLite.', }) } }) ``` 을 위한`submit_plan`, resume with `{ action: 'approved' }` or `{ action: 'rejected', feedback }`. 승인된 plan은 다음으로 구성된 Mode로 전환할 수 있습니다: `transitionsTo` before the run continues. ## 하위 Agent에 위임 컨트롤러에서 사용 가능한 하위 Agent 유형을 구성합니다. 내장`subagent` Tool은 이후 해당 정의를 사용해 범위가 명확한 작업을 위임할 수 있습니다: ```typescript const controller = new AgentController({ tools: { searchDocs, }, subagents: [ { id: 'code-reviewer', name: 'Code reviewer', description: 'Review a change for correctness and regressions.', instructions: 'Inspect the change and report actionable findings.', allowedControllerTools: ['searchDocs'], allowedWorkspaceTools: ['view', 'find_files'], defaultModelId: 'openai/gpt-5-mini', }, ], }) ``` 일반 하위 Agent는 구성된 지침과 제한된 Tool 세트로 시작됩니다. 세트`forked: true` 자식이 상위 thread를 복제하고 상위 Agent의 instructions 및 Tools로 실행되어야 할 때 사용합니다. 분기된 하위 Agent는 상위 Prompt 접두사를 유지하고, definition의 instructions, Tools, allowlists, 기본 Model을 무시하며, controller에 Memory가 있어야 합니다. 사용[`session.subagents.model.set()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session) 하나의 기본 subagent Model 또는 특정 Agent type의 Model을 저장할 때 사용합니다. 다음을 사용해 선택 사항을 읽으세요: [`session.subagents.model.get()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session): ```typescript await session.subagents.model.set({ modelId: 'openai/gpt-5-mini', }) await session.subagents.model.set({ agentType: 'code-reviewer', modelId: 'anthropic/claude-sonnet-4-6', }) const reviewerModel = session.subagents.model.get({ agentType: 'code-reviewer', }) ``` 이러한 선택 사항은 스레드 설정에 기록됩니다. Agent 유형 선택은 세션의 기본 하위 Agent Model보다 우선합니다. ## 채팅 채널 연결 채널 어댑터를 컨트롤러에 전달하고 이를 컨트롤러에 등록합니다.[`Mastra`](https://mastra.zisheng.pro/ko/reference/core/mastra-class) instance: ```typescript import { Mastra } from '@mastra/core' import { AgentController } from '@mastra/core/agent-controller' import { createSlackAdapter } from '@chat-adapter/slack' const controller = new AgentController({ id: 'support-controller', agent, storage, workspace, modes, channels: { adapters: { slack: createSlackAdapter(), }, resolveResourceId: ({ thread, message, defaultResourceId }) => { if (thread.isDM) return message.author.userId return defaultResourceId }, onSessionStart: async ({ session, thread }) => { const plan = await billing.planFor(thread.resourceId) await session.model.switch({ modelId: plan.modelId }) }, }, }) export const mastra = new Mastra({ agentControllers: { controller }, storage, }) ``` 컨트롤러별 경로에서 각 플랫폼 웹후크를 가리킵니다. ```text /api/agent-controllers//channels//webhook ``` 각 외부 채팅 스레드는 하나의 컨트롤러 세션 및 Mastra 스레드에 매핑됩니다. 기본적으로 새 세션은 어댑터의 채팅 스레드 ID에서 파생된 리소스 ID를 사용합니다.`channel:`. Use `resolveResourceId` 직접 메시지를 기존 애플리케이션 사용자에게 매핑하거나 다른 Memory 소유자를 선택할 때 사용합니다. callback은 새 thread에만 영향을 주며, 기존 thread는 저장된 resource ID를 유지합니다. 채널 세션은 코드가 아닌 컨트롤러에 의해 생성되므로`onSessionStart` 에서 이를 구성합니다. Session이 매핑된 thread에 바인딩된 후 첫 번째 메시지가 처리되기 전에 Session당 한 번 실행됩니다. channel Session이라면 누락될 수 있는 Model, Memory 설정 또는 Session 상태를 적용할 때 사용하세요. 동일한 thread의 이후 메시지는 Session을 재사용하며 이를 다시 호출하지 않습니다. 오류는 기록된 후 무시되므로 구성할 수 없는 Session도 메시지에 계속 응답합니다. 컨트롤러 채널 세션과 자동 승인 상태는 Memory에 보관되므로 수명이 긴 서버를 사용하세요. 보류 중인 승인 및 라이브 세션 상태는 프로세스를 다시 시작해도 유지되지 않습니다. 승인 제어를 렌더링할 수 없는 어댑터는 승인 메시지 없이 자동으로 Tool을 실행하므로 실행이 일시 중단된 상태로 유지되지 않습니다. 보다[Channels](https://mastra.zisheng.pro/ko/docs/capabilities/channels/overview) for adapter setup and platform-specific webhook configuration. ## UI 연결 증분 업데이트를 위해 세션 이벤트를 구독하세요. 축소된 표시 상태를 읽으십시오.[`session.displayState.get()`](https://mastra.zisheng.pro/ko/reference/agent-controller/session) UI에 완전한 rendering snapshot이 필요할 때 사용합니다: ```typescript const unsubscribe = session.subscribe(event => { if (event.type === 'display_state_changed') { render(event.displayState) } }) render(session.displayState.get()) // Call when the UI disconnects. unsubscribe() ``` 구독은 세션별로 격리됩니다. 동일한 컨트롤러에 있는 다른 세션의 이벤트는 이 리스너로 전달되지 않습니다. 읽기[Building a coding agent](https://mastra.zisheng.pro/ko/guides/guide/coding-agent) guide for a complete TUI example. ## 관련된 - [Agent](https://mastra.zisheng.pro/ko/docs/agents/overview) - [작업공간](https://mastra.zisheng.pro/ko/docs/workspace/overview) - [관찰 기억](https://mastra.zisheng.pro/ko/docs/memory/observational-memory) - [채널](https://mastra.zisheng.pro/ko/docs/capabilities/channels/overview)