문제
AI가 코드를 생성하는 데모는 흔합니다.
prompt
-> generated files
-> run command
하지만 제품 안에서 이걸 그대로 실행하면 위험합니다.
- 어떤 파일이 생성됐는지 추적하기 어렵다.
- 사용자가 review하기 전에 command가 실행될 수 있다.
- install/network command가 무제한으로 실행될 수 있다.
- 실패 후 agent가 무한 repair loop에 빠질 수 있다.
- 결과 preview가 제품 object로 남지 않는다.
OpenCairn의 code workspace는 generated code를 chat text가 아니라 project object로 다룹니다.
관련 코드
주요 경로는 다음입니다.
packages/shared/src/code-project-workspaces.ts
packages/shared/src/agent-actions.ts
apps/api/src/routes/agent-actions.ts
apps/worker/src/worker/workflows/code_workspace_command_workflow.py
apps/worker/src/worker/workflows/code_workspace_install_workflow.py
apps/worker/src/worker/workflows/code_workspace_repair_workflow.py
shared package는 code project/workspace의 contract를 정의합니다. API는 action validation과 approval boundary를 담당합니다. worker는 실제 command, install, repair workflow를 실행합니다.
generated code는 artifact가 아니라 workspace다
단순 generated file 목록만 저장하면 다음 작업이 어렵습니다.
수정
-> diff
-> command run
-> preview
-> repair
그래서 OpenCairn은 code output을 workspace/project 개념으로 봅니다.
type CodeProjectWorkspace = {
id: string;
workspaceId: string;
title: string;
files: CodeProjectFile[];
runtime: "node" | "python" | "static";
status: "draft" | "ready" | "running" | "failed";
};
이 모델이 있어야 UI에서 file tree, patch preview, command log, static preview를 연결할 수 있습니다.
command run은 action이다
OpenCairn에서는 command 실행도 free-form으로 처리하지 않습니다.
packages/shared/src/agent-actions.ts의 action kind 안에는 code project 관련 action이 포함됩니다.
export const agentActionKindSchema = z.enum([
"code_project.command.run",
"code_project.dependency.install",
"code_project.repair",
]);
명령 실행 요청은 action으로 기록되고, risk/approval policy를 통과합니다.
user or agent requests command
-> create code_project.command.run action
-> validate workspace/project scope
-> classify risk
-> require approval when needed
-> start worker workflow
-> stream logs/output
-> update workflow run
이 경계가 없으면 LLM이 만든 command를 제품이 그대로 실행하게 됩니다.
install과 network는 별도 approval surface다
코드 실행에서 가장 위험한 부분은 dependency install과 network access입니다.
예를 들어 agent가 이런 명령을 제안할 수 있습니다.
npm install some-package
curl https://example.com/script.sh | sh
이 둘을 같은 command로 취급하면 안 됩니다.
OpenCairn은 install workflow를 별도로 둡니다.
code_workspace_install_workflow.py
-> dependency request
-> approval required
-> bounded install
-> lockfile/result capture
설계상 중요한 점은 "실행 가능하다"와 "자동 실행해도 된다"가 다르다는 것입니다.
repair loop
AI code workflow에서 실패는 정상 경로입니다.
generated app
-> npm run build
-> type error
-> repair patch
-> rerun
하지만 repair를 무한히 돌리면 안 됩니다. 그래서 OpenCairn의 repair workflow는 bounded loop여야 합니다.
개념적으로는 이런 구조입니다.
@workflow.defn
class CodeWorkspaceRepairWorkflow:
@workflow.run
async def run(self, input: RepairInput) -> RepairResult:
attempts = []
for attempt_index in range(input.max_attempts):
patch = await workflow.execute_activity(
propose_repair_patch,
RepairAttemptInput(input=input, attempts=attempts),
)
result = await workflow.execute_activity(
apply_and_verify_patch,
patch,
)
attempts.append(result)
if result.verification_passed:
return RepairResult(status="completed", attempts=attempts)
return RepairResult(status="failed", attempts=attempts)
중요한 것은 repair가 workflow run에 기록되고, 각 attempt가 결과를 남긴다는 점입니다.
preview lifecycle
코드 생성 결과는 사용자가 눈으로 확인할 수 있어야 합니다.
OpenCairn의 code workspace는 command output뿐 아니라 static preview/provider URL 같은 output을 Workflow Console로 넘길 수 있습니다.
files generated
-> build/run command
-> preview URL
-> Workflow Console output
-> user opens/reviews
이 구조가 있으면 code agent는 단순 generator가 아니라 "만들고, 실행하고, 검증하고, 보여주는" workflow가 됩니다.
구현하며 배운 점
AI code feature에서 핵심은 code generation 품질만이 아닙니다.
더 중요한 것은 실행 경계입니다.
생성된 파일을 어디에 보관할 것인가?
실행 명령을 누가 승인하는가?
install/network를 어떻게 제한하는가?
실패한 build를 몇 번까지 고칠 것인가?
preview와 log를 어디에 남길 것인가?
OpenCairn의 code workspace는 이 질문에 답하기 위해 action ledger, worker workflow, Workflow Console을 하나로 연결합니다.