전체 글 (188) 썸네일형 리스트형 Redis Streams consumer group으로 Python inbox stream 처리하기 본문Redis Streams를 inbox로 쓰기 시작하면, 가장 먼저 부딪히는 건 "어느 worker가 어떤 메시지를 맡았는가"다. 단순 queue처럼 읽기만 하면 끝날 것 같지만, 실제로는 처리 중 중단, 재시도, 회수, 종료 시 정리까지 같이 설계해야 한다. 이럴 때 consumer group이 가장 단순한 해법이 된다.consumer group을 쓰면 하나의 stream을 여러 worker 인스턴스가 나눠 읽는다. 새 메시지는 한 consumer에게만 배정되고, 처리 결과는 ACK으로 정리한다. 멈춘 메시지는 pending에 남겨 두었다가 나중에 회수할 수 있다. 핵심은 "한 번 읽고 끝"이 아니라, 상태를 Redis에 남겨 두고 다시 수습할 수 있게 만드는 것이다.consumer group으로 나.. SQS worker와 Redis response stream을 연결하는 장기 실행 작업 패턴 본문장기 실행 작업은 HTTP 요청 안에서 끝내기보다 SQS worker로 넘기는 편이 낫다. 다만 큐에서 작업을 꺼내는 것만으로는 충분하지 않다. 성공 결과, 에러 결과, 종료 신호를 Redis response stream에 먼저 남기고 나서야 SQS 메시지를 delete할지, 다시 보이게 할지, visibility timeout 재시도에 맡길지 결정할 수 있다.이 글의 핵심은 “SQS 메시지 처리 결과”와 “Redis response stream의 종료 상태”를 같은 것으로 보지 않는 것이다. 큐 메시지는 작업 실행권을 나타내고, response stream은 클라이언트가 읽을 결과 계약을 나타낸다. 둘을 분리해야 장기 실행 작업의 실패 경계가 흐려지지 않는다.control flow를 먼저 표로 고정.. Agent Safety boundary를 독립 runtime으로 분리하는 기술 패턴 본문생성 runtime 안에 safety check를 같이 넣으면 코드가 빨리 엉킨다. 생성은 생성대로, safety는 safety대로 요구사항이 다르기 때문이다. 하나의 함수에서 텍스트 생성, 안전성 판정, 예외 처리, fallback, 응답 재작성까지 같이 맡기면 경계가 사라진다. 그 순간부터 caller는 “무엇이 생성 결과이고 무엇이 safety result인지”를 더 이상 분리해서 다루기 어렵다.이럴 때 필요한 패턴이 AI safety boundary다. 핵심은 safety를 generation runtime의 내부 로직으로 보지 않고, 독립 boundary로 다루는 것이다. 생성 쪽은 결과를 소비할 뿐이고, safety 쪽은 별도의 contract로 safety_result를 돌려준다.boun.. Python async gRPC 서비스와 protobuf contract 운영 본문grpc.aio 서버를 빨리 띄우는 것보다 먼저 해야 할 일은 protobuf contract를 고정하는 것이다..proto는 계약이고, _pb2.py와 _pb2_grpc.py는 생성 산출물이며, servicer는 구현이고, server bootstrap은 연결부다. 이 네 가지를 섞으면 field number 관리, codegen drift, timeout, gRPC status mapping이 한꺼번에 흔들린다..proto는 Python 코드보다 먼저 보는 계약이다공개 예시는 실제 서비스명이 아니라 형태만 보여주는 generic contract다.syntax = "proto3";package example;service ExampleService { rpc ExampleMethod (Exampl.. LLM JSON 실패를 견디는 deterministic fallback 테스트 본문LLM structured output은 JSON 문자열을 받는 순간 끝나지 않는다. json.loads를 통과해도 schema validation에서 깨질 수 있고, 복구 가능한 malformed JSON과 그냥 자연어 텍스트를 같은 실패로 취급하면 런타임은 빈 결과나 예외로 무너진다.핵심은 실패 처리 순서를 먼저 고정하는 것이다.parse: 표준 JSON 파서를 먼저 시도한다. 실패하면 복구 후보로 넘긴다.repair: 명백히 malformed인 입력만 best-effort로 고친다. 실패하면 원본을 유지하거나 None으로 둔다.validate: 같은 schema model로 의미를 검증한다. 실패하면 retry를 한 번만 허용한다.fallback: 입력에서만 만든 안정적인 값으로 대체한다. 빈 .. 메시지 envelope로 요청 메타데이터를 안정화하는 법 본문비동기 요청을 스트림으로 오래 흘리다 보면 payload보다 metadata가 먼저 흔들린다. resource_id가 비어 있고, target은 어떤 경로에서는 payload 안에 있고 다른 경로에서는 envelope 최상단에 있다. auth_context는 객체였다가 문자열이었다가 한다. 이 글에서 다루는 구현 경로에서는 Redis Streams field 값이 문자열로 decode되므로, envelope 경계에서 타입을 다시 복원하는 과정이 특히 중요해진다.필드 몇 개를 덧붙이는 정도로는 해결되지 않는다. 필요한 건 요청 경계를 통과하는 metadata를 한 곳에서 정리하는 message envelope다. raw message를 그대로 downstream에 넘기지 말고, envelope 경계에서.. 명시적 context payload로 LLM 출력 포맷 제어하기 본문사용자가 “HTML로 만들어줘”라고 적었다고 해서 시스템이 항상 HTML을 내보내는 건 아니다. 텍스트는 쉽게 바뀌고, 복사되기 쉽고, 중간에 다른 문장이 끼어들기 쉽다. 반면 출력 포맷은 렌더링 단계까지 일관되게 유지돼야 한다. 그래서 포맷은 프롬프트 문구가 아니라 명시적 context payload의 필드로 다루는 편이 안전하다.여기서 설명하는 정책은 문서형 LLM 런타임 한정의 설계 예시다. 다른 에이전트나 다른 제품에서는 기본값과 허용 포맷이 달라질 수 있다. 중요한 건 구조화된 메타데이터를 정식 신호로 두고, 텍스트 해석은 아주 좁은 보조 경로로만 제한하는 것이다.왜 프롬프트 문구만으로는 부족한가자연어는 편하지만 계약으로 쓰기엔 약하다.같은 문구가 메시지 중간에 섞여 들어갈 수 있다.번역이나.. Python AI 에이전트 패키지 아키텍처 본문여러 AI 런타임을 한 repo에 넣으면 가장 먼저 무너지는 건 구현이 아니라 경계다. 어느 패키지가 외부에 공개하는 계약인지, 어디까지가 내부 런타임인지, 공통 레이어가 어느 방향으로만 의존해야 하는지가 흐려지면 에이전트 수가 늘어날수록 import가 번지고 배포 단위도 꼬인다.이 문제를 풀 때 중요한 건 “모든 에이전트가 똑같아야 한다”가 아니다. 각 에이전트는 자기 런타임을 가질 수 있고, 실제 구현도 달라질 수 있다. 대신 외부에서 기대할 수 있는 공개 표면은 작고 안정적이어야 한다.패키지 하나를 하나의 계약 단위로 본다AI 에이전트 패키지는 보통 아래처럼 나눌 수 있다. 실제 디렉터리 이름은 프로젝트마다 달라도 된다.agents//├── manifest.py├── entrypoint.py├─.. 이전 1 2 3 4 ··· 24 다음