AI agent
νμ¬μμ λ°λ‘ μ°λ μ 무μλν AI μμ΄μ νΈ (w. n8n, LangGraph) κ°μλ₯Ό μμ½ν λ΄μ©μ λλ€.
n8n
Flexible AI workflow automation
λ€μν μΉ μλΉμ€, μ±, APIλ€μ μ°κ²°νμ¬ μλν μν¬νλ‘μ°λ₯Ό λ§λλ μ€νμμ€ ν΅ν© νλ«νΌ
n8nμ μν¬νλ‘μ°λ₯Ό ꡬμ±νλ λ Έλ(Node)λ€λ‘ μ΄λ£¨μ΄μ Έ μμΌλ©°, κ° λ Έλλ νΉμ μμ μ μνν©λλ€.
ππ» n8n 컨ν μ΄λ ꡬλ
docker volume create n8n_data
docker run -d -it --rm --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8nEmail Agent
ππ» Gmail Actions
Gmail API μ¬μ©νκΈ°
GCP console β API λ° μλΉμ€ β API λ° μλΉμ€ μ¬μ© μ€μ β Gmail API -> νμ±ν
μ¬μ©μ μΈμ¦ μ 보 λ§λ€κΈ° β OAuth ν΄λΌμ΄μΈνΈ ID λ§λ€κΈ°
Gmail APIλ‘ μ΄μ©ν μ μλ λ€μν action, trigger κΈ°λ₯μ μ°λ κ°λ₯

ππ» Basic LLM Chain
λ΅μ₯ μ¬λΆ νλ¨
λͺ¨λΈ μ°κ²° β Prompt β
"=μλ μ΄λ©μΌ λ΄μ©μ λ³΄κ³ , λ΅μ₯μ΄ νμν μ΄λ©μΌμΈμ§ νλ¨ν΄μ£ΌμΈμ. λ§μ½ λΉμ μ μ€νμΌλ‘ μ κ° μ΄λ©μΌμ λ΅μ₯μ νμ§ λͺ»νκ²λλ©΄ μ
무μ μ°¨μ§μ΄ μκΈΈ μ μμΌλ μ£Όμν΄μ£ΌμΈμ.\n\n1. μ
무 νμ
λ©μΌμλ κ°κΈμ μ΄λ©΄ λ΅μ₯μ ν΄μΌν©λλ€. \n2. λ§μΌν
μ΄λ λ΄μ€λ ν°μ κ²½μ°μλ λ΅μ₯μ ν νμκ° μμ΅λλ€.\n\nμ΄λ©μΌ λ΄μ©:\n {{ $json.text }}",Chat Messages
"λΉμ μ μ
무λ μ΄λ©μΌμ λ΅μ₯μ ν΄μΌνλμ§ λ§μμΌνλμ§ κ²°μ νλ κ²μ
λλ€. λ΅μ₯μ΄ νμνλ€λ©΄ true, λ΅μ₯μ΄ νμ μλ€λ©΄ falseλ₯Ό 리ν΄ν΄μ£ΌμΈμ"Require Specific Output Format
{
"type": "object",
"properties": {
"need_reply": {
"type": "boolean"
}
}
}μ΄λ©μΌ λ΅μ₯ μμ±
Prompt
"=μλ μ΄λ©μΌμ λ³΄κ³ λ΅μ₯μ μμ±ν΄μ£ΌμΈμ\n\nμ΅κ·Ό λ©μΌ:\n{{ $('Gmail Trigger').item.json.text }}\n\nμ΄λ©μΌ νμ€ν 리:\n{{ $json.messages.filter(item => item.snippet) }}",Require Specific Output Format
{
"type": "object",
"properties": {
"title": {
"type": "string"
},
"content": {
"type": "string"
}
}
}
μ΄λ©μΌ μμ± λ΄
System Messages
"λΉμ μ μ΄λ©μΌ μμ± λμ°λ―Έμ
λλ€. μ¬μ©μμ μ§λ¬Έμ λ°νμΌλ‘, μ¬μ©μμκ² νμν μ΄λ©μΌμ μμ±ν΄μ£ΌμΈμ \n\nλΉμ μ΄ μ΄λ©μΌμ μμ±νλλ° νμν λͺ¨λ μ 보λ₯Ό μ»μ λκΉμ§ μ¬μ©μμκ² μ§λ¬Έμ ν νμ, νμν μ 보λ₯Ό λͺ¨λ μ»κ³ λμ μ΄λ©μΌμ μμ±ν΄μ£ΌμΈμ"News Agent (Brave Search API)
ππ» Schedule Trigger
μν¬νλ‘μ°λ₯Ό νΉμ μκ°μ μλμΌλ‘ μμμν€λ λ Έλ
μ§μ λ μκ° κ°κ²©(μ: λ§€μΌ μ€μ 9μ, λ§€μ£Ό μμμΌ, 15λΆλ§λ€ λ±)μ λ§μΆ° λ€μ λ Έλλ‘ λ°μ΄ν°λ₯Ό μ λ¬νλ©° μν¬νλ‘μ°λ₯Ό μ€ν
America/New_York Timezone μ΄λ―λ‘ νκ΅ μκ°λ κ³μ°μ΄ νμ
ππ» Brave Search
Brave Search μμ§μ μ΄μ©ν΄ μΉ κ²μμ μννκ³ , κ·Έ κ²°κ³Όλ₯Ό n8n μν¬νλ‘μ°λ‘ κ°μ Έμ€λ λ Έλ
κ²μ κ²°κ³Όλ₯Ό JSON ννλ‘ λ°μμμ λ€λ₯Έ λ Έλμμ νμ©
ππ» Code
μν¬νλ‘μ° λ΄μμ JavaScript μ½λλ₯Ό μ§μ μ€νν μ μλ λ Έλ
n8nμ κΈ°λ³Έ λ Έλλ§μΌλ‘λ ν΄κ²°νκΈ° μ΄λ €μ΄ 볡μ‘ν λ‘μ§μ ꡬννκ±°λ, λ°μ΄ν°λ₯Ό νΉμ ννλ‘ κ°κ³΅ν΄μΌ ν λ μ μ©
n8nμ λͺ¨λ λ Έλμμ μ λ¬λ°μ λ°μ΄ν°λ₯Ό μ½λ λ Έλμμ μ²λ¦¬ κ°λ₯
return $input.first().json.results
ππ» Loop Over Items
μν¬νλ‘μ°κ° λ°°μ΄(리μ€νΈ) ννμ λ°μ΄ν° μμ΄ν λ€μ νλμ© μννλ©° λ°λ³΅ μμ μ μννλλ‘ νλ λ Έλ
κ° μμ΄ν μ λν΄ λμΌν μΌλ ¨μ μμ μ μ μ© κ°λ₯
Batch Size μ§μ
ππ» Basic LLM Chain
LangChainJS λΌμ΄λΈλ¬λ¦¬λ₯Ό κΈ°λ°μΌλ‘ LLMκ³Ό μνΈμμ©νλ λ Έλ
볡μ‘ν μ½λ© μμ΄λ ν둬ννΈ ν νλ¦Ώκ³Ό LLMμ μ°κ²°νμ¬ ν μ€νΈλ₯Ό μμ±νκ±°λ, μ§λ¬Έ-λ΅λ³ κΈ°λ₯μ μν¬νλ‘μ°μ ν΅ν© κ°λ₯
Prompt
"Categorize below news article by reading the description into \"positive,\" \"negative,\", \"neutral\":\n\nNews Article:\nTitle: {{ $json.title }}\nDescription: {{ $json.description }}\nURL: {{ $json.url }}",Chat Messages
"Your job is to analyze the sentiment of a news article from a user every morning and report to the executives and share with my colleagues\n\nAfter analyzing the sentiment, use the Google Sheet Tool provided to you to insert the analysis into the spreadsheet for other colleagues to see"Require Specific Output Format
{
"type": "object",
"properties": {
"sentiment": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"url": {
"type": "string"
}
}
}ππ» Append row in sheet
Google Sheets, Excel λ± μ€νλ λμνΈ μλΉμ€μ μλ‘μ΄ νμ μΆκ°νλ λ Έλ
μν¬νλ‘μ°μμ μ²λ¦¬λ λ°μ΄ν°λ₯Ό μ΅μ’ μ μΌλ‘ μ€νλ λμνΈμ μ 리ν λ μ¬μ©
Google Drive & Google Sheets API
GCP console β API λ° μλΉμ€ β API λ° μλΉμ€ μ¬μ© μ€μ
Google Drive API
Google Sheets API
μ¬μ©μ μΈμ¦ μ 보 λ§λ€κΈ° β OAuth ν΄λΌμ΄μΈνΈ ID λ§λ€κΈ° (κΈ°μ‘΄ ID μ¬μ© κ°λ₯)
μνΈμ ν€λ μΆκ° β Document & Sheet μ ν β ν€λ μ 보 μ λ ₯

Result

Brave News μΆμΆ (Brave Search)
μΆμΆλ μ 보λ₯Ό JSON ννλ‘ λ³ν (Code)
Loop Over Items
λ΄μ€ κ°μ λΆμ (Basic LLM Chain)
κ²°κ³Όλ₯Ό μνΈμ μΆκ° (Sheets)

News Agent (Naver HTTP Request)
ππ» HTTP Request
μΉμμ λ°μ΄ν°λ₯Ό κ°μ Έμ€κ±°λ 보λ΄λ κ°μ₯ κΈ°λ³Έμ μΈ λ Έλ
νΉμ URLλ‘ HTTP μμ²(GET, POST, PUT, DELETE λ±)μ 보λ΄κ³ , κ·Έ μλ΅μ λ°μ μν¬νλ‘μ°μ ν΅ν©
APIμμ μνΈμμ©μ λλΆλΆ μ΄ λ Έλλ₯Ό ν΅ν΄ μ΄λ£¨μ΄μ§
ππ» HTML
HTML λ¬Έμμμ νΉμ λ°μ΄ν°λ₯Ό μΆμΆνλ λ° μ¬μ©
μΉ μ€ν¬λν(Web Scraping)μ ν΅μ¬ λ Έλ
CSS μ λ ν°(Selector)λ₯Ό μ΄μ©ν΄ μνλ νκ·Έλ ν΄λμ€, μμ΄λλ₯Ό κ°μ§ μμλ₯Ό μ ννκ³ κ·Έ μμ ν μ€νΈλ μμ± κ°μ μΆμΆ
ππ» Filter
λ°μ΄ν°λ₯Ό νΉμ 쑰건μ λ°λΌ κ±Έλ¬λ΄λ λ Έλ
μ λ ₯ λ°μ΄ν°κ° μ€μ λ 쑰건μ λ§μ‘±νλμ§ νμΈνμ¬, 쑰건μ λ§μ‘±νλ λ°μ΄ν°λ§ λ€μ λ Έλλ‘ μ λ¬
쑰건μ λ±νΈ, λΆλ±νΈ, ν¬ν¨ μ¬λΆ, μ κ·μ λ± λ€μνκ² μ€μ
ππ» Notion
Notion λ°μ΄ν°λ² μ΄μ€ λλ νμ΄μ§μ μνΈμμ©νλ λ Έλ
Notion κ³μ κ³Ό μ°κ²°νμ¬ λ°μ΄ν°λ² μ΄μ€μ μλ‘μ΄ νλͺ©μ μΆκ°νκ±°λ, κΈ°μ‘΄ νμ΄μ§μ λ΄μ©μ μ λ°μ΄νΈνκ±°λ, νΉμ λ°μ΄ν°λ₯Ό κ²μνλ λ±μ μμ μ μν
Notion Credential
notion integration β View my integrations β New API integration β Notion μ΅μ β μ°κ²° β API integration μ°κ²°
Result

κΈ°μ¬ λͺ©λ‘ μμ² (HTTP Request)
Loop Over Items
κΈ°μ¬ μ λͺ© & URL μΆμΆ (HTML)
μΆμΆλ μ 보λ₯Ό JSON ννλ‘ λ³ν (Code)
Loop Over Items
κΈ°μ¬ URL μμ² (HTTP Request)
κΈ°μ¬ λ΄μ© μΆμΆ (HTML)
μ°κ΄μ± νμ (Basic LLM Chain)
μ°κ΄μ±μ΄ μλμ§ νν°λ§ (Filter)
λ΄μ€ κ°μ λΆμ (Basic LLM Chain)
λ Έμ λ°μ΄ν°λ² μ΄μ€μ μΆκ° (Notion)

n8nμ νμ©ν μ¬λ΄ QnA Bot
λ°μ΄ν° μ μ₯
ππ» Get rows in sheet
Google Sheets, Excel λ± μ€νλ λμνΈμμ νΉμ νλ€μ μ½μ΄μ€λ λ Έλ
νν°λ§ 쑰건μ μ€μ νμ¬ νΉμ νλ§ μ νμ μΌλ‘ κ°μ Έμ¬ μ μμΌλ©°, κ°μ Έμ¨ λ°μ΄ν°λ μν¬νλ‘μ°μ λ€μ λ Έλλ‘ μ λ¬λμ΄ κ°κ³΅λκ±°λ νμ©
ex) νμΌ λ§ν¬ λͺ©λ‘ κ°μ Έμ€κΈ°
ππ» Download file
νΉμ URLμμ νμΌμ λ€μ΄λ‘λνμ¬ μν¬νλ‘μ°λ‘ κ°μ Έμ€λ λ Έλ
λ€μ΄λ‘λλ νμΌμ λ€μ λ Έλμμ μ²λ¦¬ν μ μλ ννλ‘ λ³ν
ex) μΆμΆλ νμΌ λ§ν¬λ₯Ό μ½κ³ ν΄λΉ νμΌμ λ€μ΄λ‘λ
ππ» Pinecone Vector Store
μ λ¬Έ λ²‘ν° λ°μ΄ν°λ² μ΄μ€μ λ°μ΄ν°λ₯Ό μ μ₯νκ±°λ κ²μ
LLM μ ν리μΌμ΄μ μμ λ°©λν μμ λΉμ ν λ°μ΄ν°λ₯Ό ν¨μ¨μ μΌλ‘ κ²μνκ³ κ΄λ¦¬νλ λ° μ¬μ©
Gemini
Pinecone Vector Store λ Έλμ ν¨κ» μ¬μ©λλ Gemini λ Έλλ Googleμ Gemini AI λͺ¨λΈμ μ¬μ©νμ¬ ν μ€νΈ λ°μ΄ν°λ₯Ό 벑ν°λ‘ λ³ννλ μν μ
벑ν°νλ λ°μ΄ν°λ Pinecone λ°μ΄ν°λ² μ΄μ€μ μ μ₯λμ΄ μ μ¬λ κ²μμ μ¬μ©
Default Data Loader
λ€μν μμ€(μΉμ¬μ΄νΈ, PDF, CSV νμΌ λ±)μμ λ°μ΄ν°λ₯Ό λΆλ¬μμ μ²λ¦¬ κ°λ₯ν ννλ‘ λ³ννλ μν
μ΄ λ Έλλ νΉν LLM μν¬νλ‘μ°μμ μΈλΆ λ°μ΄ν°λ₯Ό λͺ¨λΈμ μ λ ₯νκΈ° μ μ μ μ²λ¦¬νλ λ° μ¬μ©
Recursive Character Text Splitter
κΈΈκ³ λ³΅μ‘ν ν μ€νΈλ₯Ό LLMμ΄ ν λ²μ μ²λ¦¬νκΈ° μ ν©ν ν¬κΈ°μ 'λ©μ΄λ¦¬(chunk)'λ‘ λλλ μν
νΉμ λ¬Έμ(μ: '\n\n', '\n', '.' λ±)λ₯Ό κΈ°μ€μΌλ‘ ν μ€νΈλ₯Ό μ¬κ·μ μΌλ‘ λΆν νμ¬, μλ―Έ μλ λ¨μκ° μμλμ§ μλλ‘ ν¨

Bot using LLM Chain
ππ» When Chat message received
ν λ κ·Έλ¨, μ¬λ λ± νΉμ λ©μ μ μ±λμμ μλ‘μ΄ λ©μμ§κ° μμ λμμ λ μν¬νλ‘μ°λ₯Ό μλμΌλ‘ μμνλ νΈλ¦¬κ±° λ Έλ
μ±ν κΈ°λ°μ μλν μν¬νλ‘μ°λ₯Ό ꡬμΆνλ λ° νμμ
ππ» Basic LLM Chain
볡μ‘ν λ¬Έμλ λ°μ΄ν° μμ€λ₯Ό λ°νμΌλ‘ μ§λ¬Έμ λν λ΅λ³μ μμ±νλ κ³ κΈ λ Έλ
μ¬μ©μμ μ§λ¬Έμ μ λ ₯μΌλ‘ λ°μ, μ°κ²°λ λ°μ΄ν° μμ€μμ κ΄λ ¨ μ 보λ₯Ό μ°Ύμλ΄κ³ , μ΄λ₯Ό λ°νμΌλ‘ LLMμ΄ μμ°μ΄ λ΅λ³μ μμ±
RAG(Retrieval Augmented Generation) κΈ°μ μ ꡬννλ λ° μ¬μ©
Vector Store Retriever
μ§λ¬Έκ³Ό κ΄λ ¨λ μ 보λ₯Ό λ²‘ν° λ°μ΄ν°λ² μ΄μ€μμ ν¨μ¨μ μΌλ‘ κ²μνλ μν
μ¬μ©μμ μ§λ¬Έμ 벑ν°λ‘ λ³νν ν, μ΄ λ²‘ν°μ μ μ¬ν μλ―Έλ₯Ό κ°μ§ κΈ°μ‘΄ λ¬Έμ 벑ν°λ€μ λ°μ΄ν°λ² μ΄μ€μμ νμ
μ΄ λ Έλλ₯Ό ν΅ν΄ LLMμ λ°©λν λ°μ΄ν° μμμ νμν μ λ³΄λ§ 'κ²μ'
Pinecone Vector Store
λ²‘ν° λ°μ΄ν°λ² μ΄μ€μ ν μ’ λ₯λ‘, Vector Store Retriever λ Έλμ ν¨κ» μ¬μ©
μ΄κ³³μ μ μ₯λ λ¬Έμ 벑ν°λ€μ κΈ°λ°μΌλ‘ κ²μ
LLMμ΄ νμ΅νμ§ μμ μ΅μ λ°μ΄ν°λ μ λ¬Έ λ¬Έμμ λν μ§μμλ΅ κΈ°λ₯μ ꡬνν λ μ£Όλ‘ νμ©
Embeddings Google Gemini
ν μ€νΈ λ°μ΄ν°λ₯Ό ꡬκΈμ Gemini AI λͺ¨λΈμ μ¬μ©νμ¬ λ²‘ν°λ‘ λ³ννλ μν
μ§λ¬Έκ³Ό λ¬Έμ λͺ¨λ μ΄ λ Έλλ₯Ό κ±°μ³ λ²‘ν°νλλ©°, μ΄ λ²‘ν°λ Vector Store Retriever λ Έλλ₯Ό ν΅ν΄ Pinecone λ°μ΄ν°λ² μ΄μ€μ μ μ₯λκ±°λ κ²μμ μ¬μ©

Bot using AI Agent
ππ» AI Agent
LLMμ μ΄μ©ν΄ 볡μ‘ν μμ μ μ€μ€λ‘ κ³ννκ³ μ€ννκ² νλ κ³ κΈ λ Έλ
λ¨μν ν μ€νΈλ₯Ό μμ±νλ κ²μ λμ΄, μ¬λ¬ λꡬλ₯Ό μ‘°ν©νκ³ μμ°¨μ μΌλ‘ μ€ννμ¬ λͺ©νλ₯Ό λ¬μ±
System Message
You are a helpful assistant. Use the tools that are available to you in order to answer the user's questionPinecone Vector Store tool
AI Agentκ° Pinecone λ²‘ν° λ°μ΄ν°λ² μ΄μ€λ₯Ό 'λꡬ'λ‘ μ¬μ©
AI Agentλ μ΄ λꡬλ₯Ό μ΄μ©ν΄ λ°μ΄ν°λ² μ΄μ€μμ νΉμ μ 보λ₯Ό κ²μνκ±°λ, μλ‘μ΄ λ°μ΄ν°λ₯Ό μ μ₯νλ λ±μ μμ μ μν¬νλ‘μ° λ΄μμ μν
tool Description
The documents within this knowledge base contains information about company's policy such as HR, IT Support, and so on
Text-to-SQL
Text-to-SQL
μμ°μ΄(μμ΄λ νκ΅μ΄)λ₯Ό SQLλ‘ λ³ννλ κΈ°μ
AIλ₯Ό ν΅ν λ°μ΄ν°λ² μ΄μ€ μ κ·Ό
ππ» When chat message received
ππ» ν
μ΄λΈ μ΄λ¦ κ°μ Έμ€κΈ°
Postgres Execute a SQL query
SELECT
col.table_name,
COALESCE(obj_description(c.oid), 'No description available') AS table_description,
string_agg(col.column_name, ', ' ORDER BY col.ordinal_position) AS all_columns
FROM information_schema.columns col
LEFT JOIN pg_class c ON c.relname = col.table_name
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE col.table_schema = 'public'
AND n.nspname = 'public'
GROUP BY col.table_name, c.oid
ORDER BY col.table_name;ππ» ν
μ΄λΈ μ 보 ν©μΉκΈ°
Code
let schema = '';
for (const item of $input.all()) {
schema += `tableName: ${item.json.table_name}
tableDescription: ${item.json.table_description}
columnList: ${item.json.all_columns}`;
}
return [{schema}];ππ» ν
μ΄λΈ 리μ€νΈ μΆμΆ
Basic LLM Chain
Prompt
{{ $('When chat message received').first().json.chatInput }}System Message
TABLE DESCRIPTION:
{{ $json.schema }}
By looking at the table description above, which contains information about the name of tables and their relative descriptions along with the list of columns, return the list of names of the tables that you need to access in order to retrieve data related to the user's questionstructured Output Parser
{
"type": "object",
"properties": {
"tables": {
"type": "array",
"table": {
"type": "string"
}
}
}
}ππ» μ€ν€λ§ μ‘°ν
Postgres Execute a SQL query
SELECT
'CREATE TABLE ' || table_name || ' (' || E'\n' ||
-- κ° μ»¬λΌμ λν μ 보λ₯Ό μ‘°ν©ν©λλ€.
string_agg(
' ' || column_name || ' ' ||
CASE
WHEN data_type = 'character varying' THEN 'VARCHAR(' || character_maximum_length || ')'
WHEN data_type = 'integer' AND column_default LIKE 'nextval%' THEN 'SERIAL PRIMARY KEY'
WHEN data_type = 'numeric' THEN 'DECIMAL(' || numeric_precision || ',' || numeric_scale || ')'
WHEN data_type = 'timestamp without time zone' THEN 'TIMESTAMP'
WHEN data_type = 'boolean' THEN 'BOOLEAN'
ELSE UPPER(data_type)
END ||
CASE WHEN is_nullable = 'NO' AND column_default NOT LIKE 'nextval%' THEN ' NOT NULL' ELSE '' END ||
CASE WHEN column_default IS NOT NULL AND column_default NOT LIKE 'nextval%'
THEN ' DEFAULT ' || column_default ELSE '' END,
E',\n' ORDER BY ordinal_position
) || E'\n' || ');' || E'\n\n' AS create_statement
FROM
information_schema.columns
WHERE
table_schema = 'public'
AND TABLE_NAME IN ({{ $json.output.tables.map((tableName) => `'${tableName}'`) }})
GROUP BY
table_name
ORDER BY
table_name;ππ» μ€ν€λ§ μ 보 ν©μΉκΈ°
Code
let schema = ''
for (const item of $input.all()) {
schema += `${item.json.create_statement}\n\n`
}
return [{schema}]ππ» 쿼리 μμ±
Basic LLM Chain
Prompt
{{ $('When chat message received').first().json.chatInput }}System message
DATABASE SCHEMA:
{{ $json.schema }}
Looking at the database schema above, convert a user's question into a SQL query to fetch data from the database. return the SQL query only Structured Output Parser
{
"type": "object",
"properties": {
"query": {
"type": "string"
}
}
}ππ» 쿼리 μ€ν
Postgres Execute a SQL query
{{ $json.output.query }}ππ» 쿼리 κ²°κ³Ό λ€λ¬κΈ°
Basic LLM Chain
Prompt
QUERY RESULT:
{{ JSON.stringify($json) }}
Original Question:
{{ $('When chat message received').first().json.chatInput }}System Message
Look at the query result and the user's question and return a user friendly message
MCP
Introducing the Model Context Protocol
MCP μ©μ΄
Protocol
ν΅μ κ³μ½μ
μΉ κ°λ°μ HTTP ν΅μ κ³Ό μ μ¬
HTTP = Hypertext Transfer Protocol (μΉ ν΅μ κ³μ½)
MCP = λͺ¨λΈκ³Ό 컨ν μ€νΈ κ°μ ν΅μ κ³μ½
Model
LLM λͺ¨λΈμ μλ―Έ
GPT, Anthropicμ Claude, Gemini λ±
νκ΅μ Upstage Solar λͺ¨λΈ λ± ν¬ν¨
Context
LLMμ μνλ κ²°κ³Όλ₯Ό μ»κΈ° μν΄ μ μ λ¬ν΄μΌ νλ μ 보
MCPλ₯Ό ν΅ν΄ ν둬ννΈμ ν΄ κ΄λ¦¬ κ°λ₯
νκ΅μ΄λ‘λ "AIμκ² μ»¨ν μ€νΈλ₯Ό μ λ¬νλ νλ‘ν μ½"
MCPμ μ₯μ
νλ‘ν μ½μ λ²μ©μ±
HTTP ν΅μ μ²λΌ μλ² μΈμ΄(Java, Python, Node)μ κ΄κ³μμ΄ ν΅μ κ°λ₯
λ€μν λͺ¨λΈ μ§μ κ°λ₯
USB-C ν¬νΈ λΉμ
곡μ λ¬Έμμμ "AI μ ν리μΌμ΄μ μ μν USB-C ν¬νΈ"λ‘ νν
μ΄λν°λ₯Ό ν΅ν΄ λͺ¨λ MCP μλ²μ λͺ¨λ MCP ν΄λΌμ΄μΈνΈ μ°κ²° κ°λ₯
Code Review Agent with MCP
ref. MCPλ₯Ό νμ©ν μ½λ리뷰 μμ΄μ νΈ μμ±νκΈ°
##########################################
# νκ²½λ³μ λΆλ¬μ€κΈ°
from dotenv import load_dotenv
load_dotenv()
##########################################
# MCP Client μΈν
import os
from langchain_mcp_adapters.client import MultiServerMCPClient
github_pat = os.getenv("GITHUB_PAT")
slack_bot_token = os.getenv("SLACK_BOT_TOKEN")
slack_team_id = os.getenv("SLACK_TEAM_ID")
slack_channel_ids = os.getenv("SLACK_CHANNEL_IDS")
mcp_client = MultiServerMCPClient({
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_TOOLSETS",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_TOOLSETS": "context,pull_requests",
"GITHUB_PERSONAL_ACCESS_TOKEN": github_pat
},
"transport": "stdio"
},
"slack": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"SLACK_BOT_TOKEN",
"-e",
"SLACK_TEAM_ID",
"-e",
"SLACK_CHANNEL_IDS",
"mcp/slack"
],
"env": {
"SLACK_BOT_TOKEN": slack_bot_token,
"SLACK_TEAM_ID": slack_team_id,
"SLACK_CHANNEL_IDS": slack_channel_ids
},
"transport": "stdio"
}
})
##########################################
# MCP Client Tool νμΈ
tool_list = await mcp_client.get_tools()
##########################################
# create react agent νμ©
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(
model="openai:gpt-4.1",
tools=tool_list,
prompt="Use the tools provided to you to answer the user's question"
)
##########################################
# μ€νΈλ¦Όν κ²°κ³Όλ₯Ό 보기 μν ν¬νΌ ν¨μ
async def process_stream(stream_generator):
results = []
try:
async for chunk in stream_generator:
key = list(chunk.keys())[0]
if key == 'agent':
# Agent λ©μμ§μ λ΄μ©μ κ°μ Έμ΄. λ©μΈμ§κ° λΉμ΄μλ κ²½μ° μ΄λ€ λꡬλ₯Ό μ΄λ»κ² νΈμΆν μ§ μ 보λ₯Ό κ°μ Έμ΄
content = chunk['agent']['messages'][0].content if chunk['agent']['messages'][0].content != '' else chunk['agent']['messages'][0].additional_kwargs
print(f"'agent': '{content}'")
elif key == 'tools':
# λꡬ λ©μμ§μ λ΄μ©μ κ°μ Έμ΄
for tool_msg in chunk['tools']['messages']:
print(f"'tools': '{tool_msg.content}'")
results.append(chunk)
return results
except Exception as e:
print(f"Error processing stream: {e}")
return results
##########################################
# ν둬νλ‘ μμ±
from langchain_core.messages import HumanMessage
human_message = """κΉνμ Pull Requestλ₯Ό νμΈνκ³ μ½λ 리뷰λ₯Ό μμ±ν΄μ£ΌμΈμ.
PRμ μ½λλ₯Ό 리뷰ν νμ, μλ νλͺ©μ νμΈν΄μ£ΌμΈμ;
1. μ½λκ° κ°μ λμλμ§
2. μμΈ‘νμ§ λͺ»ν side effectκ° μλμ§
3. 보μμ λ¬Έμ κ° λ μ μλ λΆλΆμ΄ μλμ§
μ λ΄μ©μ νμΈν΄μ PRμ μ½λ©νΈλ‘ λ¨κ²¨μ£ΌμΈμ.
κ·Έλ¦¬κ³ μ½λ©νΈλ₯Ό λ¨κΈ΄ νμ, μ¬λ μ±λμλ λ©μΈμ§λ₯Ό μ μ‘ν΄μ μμ§λμ΄μκ² μλ €μ£ΌμΈμ
μ±λ: <@C092QEJH6LB>
μμ§λμ΄: <@U092VN0DHBP>
PR URL:https://github.com/jasonkang14/sat-reading-client/pull/3 """
stream_generator = agent.astream({"messages": [HumanMessage(human_message)]}, stream_mode="updates")
##########################################
# κ²°κ³Ό νμΈ
all_chunks = await process_stream(stream_generator)
if all_chunks:
final_result = all_chunks[-1]
print("\nFinal result:", final_result)Video Summary Agent
OpenAI Whisperλ₯Ό νμ©ν μμ μμ½
Reference
An extremely fast Python package and project manager, written in Rust.
A dead simple way of OCR-ing a document for AI ingestion. Documents are meant to be a visual representation after all. With weird layouts, tables, charts, etc. The vision models just make sense!
Lecture Materials
Last updated