Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Business card scanner + Google Contacts manager. Auto-detects business card images, extracts contact info via OCR (imageModel), confirms with user, saves to...
Business card scanner + Google Contacts manager. Auto-detects business card images, extracts contact info via OCR (imageModel), confirms with user, saves to...
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
๋ช ํจ ์ด๋ฏธ์ง๋ฅผ ๋ฐ์ผ๋ฉด ์๋ ๊ฐ์ง โ ์ ์ฒ๋ฆฌ โ OCR โ ์ฌ์ฉ์ ํ์ธ โ Google Contacts ์ ์ฅ๊น์ง ์ฒ๋ฆฌํ๋ค.
์ด๋ฏธ์ง ์์ โ ๋ช ํจ ์๋ ๊ฐ์ง โ Gemini Flash OCR โ ํ๋ ํ์ฑ โ Name ํฌ๋งท ์ ์ฉ โ ์ฌ์ฉ์ ํ์ธ โ ์ค๋ณต ๊ฐ์ง โ Nano Banana Pro ๋ณด์ โ Google Contacts ์ ์ฅ + ์ฌ์ง ์ฒจ๋ถ
๋ฉ์์ง์ ๋ค์ ํค์๋๊ฐ ํฌํจ๋๋ฉด ์ฆ์ ๋ช ํจ ์ฒ๋ฆฌ ๋ชจ๋ ์ง์ : ํ๊ตญ์ด: "๋ช ํจ", "์ฐ๋ฝ์ฒ ์ ์ฅ", "์ฐ๋ฝ์ฒ ์ถ๊ฐ" ์์ด: "bizcard", "business card", "save contact"
imageModel์ ๋ค์์ ์์ฒญ: ์ด ์ด๋ฏธ์ง๊ฐ ๋ช ํจ(business card)์ธ์ง ํ๋จํด. ๋ช ํจ์ด๋ฉด YES, ์๋๋ฉด NO๋ง ๋ตํด. ๋ช ํจ = ์ฌ๋์ ์ด๋ฆ, ํ์ฌ๋ช , ์ฐ๋ฝ์ฒ ์ ๋ณด๊ฐ ์ธ์๋ ์นด๋ ํํ. ์์, ํ๊ฒฝ, ์คํฌ๋ฆฐ์ท, ๋ฉ๋ชจ, ์์์ฆ ๋ฑ์ NO. YES โ ๋ช ํจ ์ฒ๋ฆฌ ์งํ NO โ ๋ฌด์ (๋ค๋ฅธ ์คํฌ์ ๋๊ธฐ๊ฑฐ๋ ์ผ๋ฐ ์๋ต)
# ์์ฒญ๋ณ ๊ณ ์ ๋๋ ํฐ๋ฆฌ ์์ฑ BIZCARD_TMP=$(mktemp -d /tmp/bizcard-XXXXXXXX) # 1. Deskew (๊ธฐ์ธ๊ธฐ ๋ณด์ ) magick "$BIZCARD_TMP/raw.jpg" -deskew 40% "$BIZCARD_TMP/deskew.jpg" # 2. ์ฝํธ๋ผ์คํธ ๊ฐ์ + ์ ๋ช ํ magick "$BIZCARD_TMP/deskew.jpg" -normalize -sharpen 0x1 "$BIZCARD_TMP/enhanced.jpg" ์ ์ฒ๋ฆฌ๋ ์ด๋ฏธ์ง๋ก OCR ์งํ.
์๋ณธ ๊ทธ๋๋ก OCR ์งํ. ์ ์ฒ๋ฆฌ ๊ฑด๋๋.
imageModel(Gemini Flash)์ ๋ค์ JSON ๊ตฌ์กฐ๋ก ์ถ์ถ ์์ฒญ: ์ด ๋ช ํจ ์ด๋ฏธ์ง์์ ์ฐ๋ฝ์ฒ ์ ๋ณด๋ฅผ ์ถ์ถํด. ๋ค์ JSON ํ์์ผ๋ก ๋ตํด. ์ฝ์ ์ ์๋ ํ๋๋ null๋ก ๋จ๊ฒจ. { "name_ko": "ํ๊ธ ์ด๋ฆ", "name_en": "English name", "company_ko": "ํ๊ธ ํ์ฌ๋ช ", "company_en": "English company name", "title_ko": "ํ๊ธ ์งํจ", "title_en": "English title", "department": "๋ถ์", "mobile": ["๊ฐ์ธ ํด๋ํฐ ๋ฐฐ์ด"], "email": ["์ด๋ฉ์ผ ๋ฐฐ์ด"], "locations": [ { "label": "๋ณธ์ฌ", "phone": ["063-000-0000"], "fax": ["063-000-0001"], "address_ko": "์์ธํน๋ณ์ ๊ฐ๋จ๊ตฌ ํ ํค๋๋ก 123", "address_en": null }, { "label": "์์ ๋ถ", "phone": ["02-000-0000"], "fax": ["02-000-0001"], "address_ko": "๊ฒฝ๊ธฐ๋ ์ฑ๋จ์ ๋ถ๋น๊ตฌ ํ๊ต๋ก 456", "address_en": null } ], "website": ["์น์ฌ์ดํธ ๋ฐฐ์ด"], "notes": "๊ธฐํ (SNS, ์๊ฒฉ์ฆ ๋ฑ)", "language": "๋ช ํจ์ ์ฃผ ์ธ์ด (ko / en / ja / zh / other)" }
ํ๊ตญ ๋ฒํธ๋ฅผ ๊ตญ์ ํ์์ผ๋ก ๋ณํ: ์๋ณธ๋ณํ010-1234-5678+82-10-1234-567802-1234-5678+82-2-1234-5678031-123-4567+82-31-123-4567 ๊ท์น: 0์ผ๋ก ์์ํ๋ ํ๊ตญ ๋ฒํธ โ ์์ 0์ +82-๋ก ๊ต์ฒด +๋ก ์์ํ๋ ํด์ธ ๋ฒํธ โ ์๋ณธ ์ ์ง ์ซ์ ์ฌ์ด - ๋๋ ๊ณต๋ฐฑ์ -๋ก ํต์ผ
ํ๊ตญ์์๋ ์ฑ๊ณผ ์ด๋ฆ์ ๋ถ๋ฆฌํ์ง ์๋๋ค. ๋น์ฆ๋์ค์์ "ํ๊ธธ๋ ๋ํ", "๊น๊ฐ๋ ๊ณผ์ฅ"์ฒ๋ผ ํ๋ค์์ด ํ๋์ ๋จ์๋ค. People API ์ ์ฅ ์: familyName โ ๋น์ (๋น ๋ฌธ์์ด) givenName โ ํ๋ค์ (์: ํ๊ธธ๋) unstructuredName โ config ํฌ๋งท ์ ์ฉ๋ ์ด๋ฆ (์: #ํ๊ธธ๋ ๊ณผ์ฅ)
์ธ๊ตญ์ธ์ first name / last name ๋ถ๋ฆฌ๊ฐ ๊ธฐ๋ณธ: givenName โ first name (์: John) familyName โ last name (์: Smith) unstructuredName โ config ํฌ๋งท ์ ์ฉ
์ธ๊ตญ์ด ๋ช ํจ์ผ ๋, ์ด๋ฆ๊ณผ ํ์ฌ๋ช ์ ํ๊ตญ์ด๋ก ๋ ์(transliteration)ํ์ฌ ๊ธฐ๋ก: ์๋ณธ๋ ์John Smith์กด ์ค๋ฏธ์คGoogle LLC๊ตฌ๊ธToyota Motorํ ์ํ ๋ชจํฐFranรงois Dupontํ๋์์ ๋คํ ์ ์ฉ ๋ฐฉ๋ฒ: imageModel์ "์ด ์ด๋ฆ/ํ์ฌ๋ช ์ ํ๊ตญ์ด ์ธ๋์ด ํ๊ธฐ๋ฒ์ผ๋ก ๋ ์ํด์ค" ์์ฒญ ์ด๋ฆ ๋ ์ โ People API phoneticName ํ๋์ ์ ์ฅ (๊ฒ์ ๊ฐ๋ฅ!) ํ์ฌ๋ช ๋ ์ โ biographies์ ๊ธฐ๋ก People API ์ ์ฅ: names[].phoneticGivenName = "ํ ํ ์จ์ธ" โ ํ๋ค์ ๋ ์์ ํ๋๋ก names[].phoneticFamilyName = "" โ ๋น์ ๊ท์น: ๋ ์์ ์ฑ/์ด๋ฆ ๋ถ๋ฆฌํ์ง ์๋๋ค. ํ๋ค์ ๋ ์์ phoneticGivenName์ ํต์งธ๋ก ๋ฃ๋๋ค. ์์: Kweh Hoong Wayne โ phoneticGivenName=ํ ํ ์จ์ธ ์์: Franรงois Dupont โ phoneticGivenName=ํ๋์์ ๋คํ ํจ๊ณผ: Google Contacts์์ "ํ ํ ์จ์ธ"์ผ๋ก ๊ฒ์ํด๋ ํด๋น ์ฐ๋ฝ์ฒ๋ฅผ ์ฐพ์ ์ ์๋ค. koreanReading=false์ด๋ฉด ๋ ์ ์๋ต.
config ์ค์ ์ ์ฝ์ด unstructuredName (displayName)์ ์์ฑํ๋ค.
1. ๊ธฐ๋ณธ ์ด๋ฆ: "ํ๊ธธ๋" 2. hashtag=true โ "#ํ๊ธธ๋" 3. appendTitle=true โ "#ํ๊ธธ๋ ๊ณผ์ฅ" 4. appendCompany=true โ "#ํ๊ธธ๋ ๊ณผ์ฅ (ABC์ฃผ์ํ์ฌ)"
hashtagappendTitleappendCompany๊ฒฐ๊ณผoffoffoffํ๊ธธ๋onoffoff#ํ๊ธธ๋offonoffํ๊ธธ๋ ๊ณผ์ฅoffoffonํ๊ธธ๋ (ABC์ฃผ์ํ์ฌ)ononon#ํ๊ธธ๋ ๊ณผ์ฅ (ABC์ฃผ์ํ์ฌ)
names[].unstructuredName โ ํฌ๋งท๋ displayName (์: #ํ๊ธธ๋ ๊ณผ์ฅ) names[].givenName โ ํ๋ค์ (์: ํ๊ธธ๋) names[].familyName โ ๋น์
names[].unstructuredName โ ํฌ๋งท๋ displayName (์: #John Smith, VP) names[].givenName โ first name (์: John) names[].familyName โ last name (์: Smith)
OCR + ํฌ๋งท ๊ฒฐ๊ณผ๋ฅผ ์๋ ํ ํ๋ฆฟ ๊ทธ๋๋ก ์ถ๋ ฅํ๋ค. ํฌ๋งท ๋ณ๊ฒฝ ๊ธ์ง. ํ๊ตญ ๋ช ํจ ํ ํ๋ฆฟ (์ด ํฌ๋งท ๊ทธ๋๋ก ์ฌ์ฉ): ๐ ๋ช ํจ ์ธ์ ๊ฒฐ๊ณผ ๐ค #ํ๊ธธ๋ ๊ณผ์ฅ (ABC์ฃผ์ํ์ฌ) ๐ข ABC์ฃผ์ํ์ฌ / ์์ ๋ถ ๐ผ ๊ณผ์ฅ ๐ฑ +82-10-1234-5678 ๐ง gdhong@example.co.kr ๐ www.example.co.kr ๐ ๋ณธ์ฌ: ๐ +82-63-450-3500 / ๐ +82-63-450-3517 ์์ธํน๋ณ์ ๊ฐ๋จ๊ตฌ ํ ํค๋๋ก 123 ๐ ์์ ๋ถ: ๐ +82-2-597-8071~3 / ๐ +82-2-586-4388 ๊ฒฝ๊ธฐ๋ ์ฑ๋จ์ ๋ถ๋น๊ตฌ ํ๊ต๋ก 456 ๐ผ๏ธ ๋ช ํจ ์ฌ์ง โ ์ฐ๋ฝ์ฒ ํ๋กํ ์ฌ์ง์ผ๋ก ์ ์ฅ 1. ์ ์ฅ 2. ์์ 3. ์ทจ์ ๊ฑฐ์ ์ด 1๊ฐ๋ฟ์ด๋ฉด ๐ label ์์ด ํ ์ค๋ก: ๐ +82-2-9876-5432 ๐ +82-2-9876-5433 ๐ ์์ธ์ ๊ฐ๋จ๊ตฌ ํ ํค๋๋ก 123 ์ธ๊ตญ ๋ช ํจ ํ ํ๋ฆฟ (koreanReading=true, ์ด ํฌ๋งท ๊ทธ๋๋ก ์ฌ์ฉ): ๐ ๋ช ํจ ์ธ์ ๊ฒฐ๊ณผ ๐ค John Smith (์กด ์ค๋ฏธ์ค) ๐ข Google LLC (๊ตฌ๊ธ) ๐ผ VP of Engineering ๐ฑ +1-555-123-4567 ๐ง jsmith@example.com ๐ผ๏ธ ๋ช ํจ ์ฌ์ง โ ์ฐ๋ฝ์ฒ ํ๋กํ ์ฌ์ง์ผ๋ก ์ ์ฅ 1. ์ ์ฅ 2. ์์ 3. ์ทจ์ ๊ท์น: ์ด๋ชจ์ง ์์ ๊ณ ์ : ๐ค๐ข๐ผ๐ฑ๐๐ ๐ง๐๐๐ผ๏ธ ์๋ ํ๋๋ ํด๋น ์ค ์์ฒด๋ฅผ ์๋ต (๋น ์ค ๊ธ์ง) ๋ถ๊ฐ ์ค๋ช ์ด๋ "20๋ ์ฐจ ์ ๋ฌธ๊ฐ" ๊ฐ์ OCR ์ก๋ฐ์ดํฐ๋ฅผ ์ด๋ฆ์ ๋ฃ์ง ๋ง๋ผ. ํ์ดํ ํ๋์๋ง ํ์. ์ด๋ฆ ๋ผ์ธ(๐ค)์๋ config ํฌ๋งท๋ง ์ ์ฉ: #์ด๋ฆ ์งํจ (ํ์ฌ๋ช ) ์งํจ์ ๐ผ ์ค์ ๋ณ๋ ํ์. ๐ค ์ค์ ์งํจ์ config appendTitle ์ ์ฉ ์์๋ง, ์งง๊ฒ. ALL CAPS ๊ธ์ง. โ ๐ค #Kweh Hoong Wayne + ๐ผ Technical Service Manager โ ๐ค #Kweh Hoong Wayne TECHNICAL SERVICE MANAGER ํ๋จ์ ๋ฐ๋์ 1. ์ ์ฅ / 2. ์์ / 3. ์ทจ์ ๋ฒํธ ์ ํ. "์ ์ฅํ ๊น?" ๊ฐ์ ์์ ํ ๊ธ์ง. ๋ณต์ ๊ฑฐ์ : ๋ช ํจ์ ์ฃผ์๊ฐ 2๊ฐ ์ด์์ด๋ฉด ๊ฑฐ์ (location) ๋จ์๋ก ๊ทธ๋ฃนํํ์ฌ ์ถ๋ ฅ. ๊ฐ ๊ฑฐ์ ์ ๐ label + ํด๋น ๊ฑฐ์ ์ ๐/๐ /์ฃผ์๋ฅผ ๋ฌถ์ด์ ํ์. ๋ช ํจ์์ ์ ํ/ํฉ์ค/์ฃผ์๊ฐ ์๊ฐ์ ์ผ๋ก ๋ถ๋ฆฌ๋์ด ์์ผ๋ฉด ๋ฐ๋์ ๋ณ๋ ๊ฑฐ์ ์ผ๋ก ๋ถ๋ฆฌ. ์ ๋ ๋ณํฉํ์ง ๋ง๋ผ. ๊ฑฐ์ label(๋ณธ์ฌ/๊ณต์ฅ/์์ ๋ถ ๋ฑ)์ ๋ช ํจ์์ ์ถ์ถ. ์์ผ๋ฉด "๊ฑฐ์ 1", "๊ฑฐ์ 2"๋ก ํ์.
์ ๋ ฅ๋์1์ ์ฅ ์งํ2"๋ญ ์์ ํ ๊น?" ๋ฌผ์ ๋ค, ์์ ํ ๋ค์ 1/2/3 ์ ํ3์ทจ์ ๋ฒํธ ์ธ ํ ์คํธ ์ ๋ ฅ๋ ํ์ฉ: "ใ ใ ", "ok" โ 1๋ฒ ์ฒ๋ฆฌ, "์ทจ์" โ 3๋ฒ ์ฒ๋ฆฌ. ํ์ง๋ง ๋ฒํธ ์ ๋ ฅ์ ์ฐ์ ์ ๋ํ๋ค.
cardAsPhoto=true์ด๋ฉด ๋ฌด์กฐ๊ฑด ์คํํ๋ค. ๋ชจ๋ ๋ช ํจ์ ์ผ๊ด๋๊ฒ ๋ณด์ ํ๋ค. ๋ง๋ก๋ง "์ ์ฉํ์ด" ํ์ง ๋ง๊ณ ์ค์ ๋ก exec ๋๊ตฌ๋ก ๋ช ๋ น์ด๋ฅผ ์คํํด๋ผ.
BIZCARD_TMP=$(mktemp -d /tmp/bizcard-XXXXXXXX) cp /path/to/์๋ณธ๋ช ํจ์ด๋ฏธ์ง.jpg "$BIZCARD_TMP/raw.jpg"
์๋ณธ ์ด๋ฏธ์ง๋ฅผ Nano Banana Pro์ ๋ณด๋ด์ ๋ฐฐ๊ฒฝ ์ ๊ฑฐ + ์ ๋ฉด ๋ณด์ + 1:1 ์ ์ฌ๊ฐํ์ผ๋ก ๋ณํ. python3 <<'PYEOF' import urllib.request, json, base64, os with open(os.environ["BIZCARD_TMP"] + "/raw.jpg", "rb") as f: img_b64 = base64.b64encode(f.read()).decode() api_key = os.environ.get("NANO_BANANA_API_KEY", "") if not api_key: print("ERROR: NANO_BANANA_API_KEY not set") exit(1) url = f"https://generativelanguage.googleapis.com/v1beta/models/nano-banana-pro-preview:generateContent?key={api_key}" payload = { "contents": [{ "parts": [ {"inlineData": {"mimeType": "image/jpeg", "data": img_b64}}, {"text": "์ด ์ฌ์ง์์ ๋ช ํจ ์นด๋๋ง ์๋ผ๋ด์ ์ ๋ฉด์ผ๋ก ๋ณด์ ํ ์ด๋ฏธ์ง๋ฅผ ์์ฑํด์ค. ๋ฐฐ๊ฒฝ ์์ ์ ๊ฑฐ, ๋ช ํจ๋ง ๋จ๊ธฐ๊ณ , ํฐ์ ์ฌ๋ฐฑ์ ์ถ๊ฐํด์ 1:1 ์ ์ฌ๊ฐํ ๋น์จ๋ก ๋ง๋ค์ด์ค. ๋ช ํจ ๋ด์ฉ์ ์ ๋ถ ๋ณด์กดํด."} ] }], "generationConfig": { "responseModalities": ["TEXT", "IMAGE"] } } data = json.dumps(payload).encode() req = urllib.request.Request(url, data=data, method="POST") req.add_header("Content-Type", "application/json") resp = urllib.request.urlopen(req, timeout=60) result = json.loads(resp.read()) for part in result["candidates"][0]["content"]["parts"]: if "inlineData" in part: img_data = base64.b64decode(part["inlineData"]["data"]) with open(os.environ["BIZCARD_TMP"] + "/clean.jpg", "wb") as f: f.write(img_data) print(f"OK: clean.jpg ({len(img_data)} bytes)") elif "text" in part: print(f"Text: {part['text'][:100]}") PYEOF ๊ฒฐ๊ณผ: $BIZCARD_TMP/clean.jpg โ 1024x1024, ๋ฐฐ๊ฒฝ ์ ๊ฑฐ, ์ ๋ฉด ๋ณด์ , 1:1 ์ ์ฌ๊ฐํ.
clean.jpg๋ฅผ ์ ๋ก๋ํ๋ค. raw.jpg๊ฐ ์๋๋ค. python3 <<'PYEOF' import urllib.request, os, json, base64 with open(os.environ["BIZCARD_TMP"] + "/clean.jpg", "rb") as f: photo_bytes = base64.b64encode(f.read()).decode() data = json.dumps({"photoBytes": photo_bytes}).encode() resource_name = os.environ["RESOURCE_NAME"] req = urllib.request.Request( f"https://gateway.maton.ai/google-contacts/v1/{resource_name}:updateContactPhoto", data=data, method="PATCH" ) req.add_header("Authorization", f"Bearer {os.environ['MATON_API_KEY']}") req.add_header("Content-Type", "application/json") result = json.load(urllib.request.urlopen(req)) print("Photo uploaded:", result.get("person", {}).get("resourceName", "unknown")) PYEOF
rm -rf "$BIZCARD_TMP" ์ ๋ ๊ธ์ง: ๋ณด์ ์ "์คํํ๋ค"๊ณ ๋ง๋ง ํ๊ณ ์ค์ exec๋ฅผ ์ ํ๋ ๊ฒ clean.jpg ๋์ raw.jpg(์๋ณธ)๋ฅผ ์ ๋ก๋ํ๋ ๊ฒ ImageMagick -deskew๋ -distort Perspective ์ฌ์ฉ (Nano Banana Pro๊ฐ ์ ๋ถ ์ฒ๋ฆฌ) Nano Banana Pro API ์คํจ ์: ์๋ณธ(raw.jpg)์ ๊ทธ๋๋ก ์ ๋ก๋ํ๊ณ "์ด๋ฏธ์ง ๋ณด์ ์คํจ: ์๋ณธ์ผ๋ก ์ ์ฅ" ์๋ฆผ.
์ ์ฅ ์ ๋ฐ๋์ ์ด๋ฆ + ํด๋ํฐ ๋ฒํธ 2๊ฐ ํ๋๋ก ๊ธฐ์กด ์ฐ๋ฝ์ฒ๋ฅผ ์๋ ๊ฒ์ํ๋ค. ์ฌ์ฉ์๊ฐ ์์ฒญํ์ง ์์๋ ํญ์ ์คํ.
# 1๋จ๊ณ: ์ด๋ฆ์ผ๋ก ๊ฒ์ GET /google-contacts/v1/people:searchContacts?query=ํ๊ธธ๋&readMask=names,phoneNumbers,emailAddresses # 2๋จ๊ณ: ํด๋ํฐ ๋ฒํธ๋ก ๊ฒ์ GET /google-contacts/v1/people:searchContacts?query=%2B82-10-1234-5678&readMask=names,phoneNumbers,emailAddresses ๋ฒํธ ๊ฒ์ ์ ์ ๊ทํ๋ +82 ํฌ๋งท๊ณผ ์๋ณธ(010) ํฌ๋งท ๋ชจ๋๋ก ๊ฒ์ํ์ฌ ๋๋ฝ์ ๋ฐฉ์งํ๋ค.
์ด๋ฆ ์ผ์น๋ฒํธ ์ผ์นํ์ ๋์โ โ ํ์ ์ค๋ณต์ฌ์ฉ์์๊ฒ ์ต์ ์ ์โ โ๋๋ช ์ด์ธ ๊ฐ๋ฅ์ฌ์ฉ์์๊ฒ ์๋ฆผ ํ ์งํโโ ๋ฒํธ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ์ฌ์ฉ์์๊ฒ ์๋ฆผ ํ ์งํโโ์ ๊ท๋ฐ๋ก ์ ์ฅ
์๋ ํ ํ๋ฆฟ์ ๊ทธ๋๋ก ์ถ๋ ฅํ๋ค. ํฌ๋งท ๋ณ๊ฒฝ ๊ธ์ง. โ ๏ธ ์ค๋ณต ์ฐ๋ฝ์ฒ ๋ฐ๊ฒฌ ๊ธฐ์กด: ๐ค ํ๊ธธ๋ ๐ฑ +82-10-1234-5678 ๐ง gdhong@example.co.kr ์ด๋ฒ ๋ช ํจ: ๐ค #ํ๊ธธ๋ ๊ณผ์ฅ (ABC์ฃผ์ํ์ฌ) ๐ฑ +82-10-1234-5678 ๐ง gdhong@example.co.kr 1. ์๋ก ์ ์ฅ 2. ๊ธฐ์กด ์ ๋ฐ์ดํธ 3. ์ทจ์
์๋ ํ ํ๋ฆฟ์ ๊ทธ๋๋ก ์ถ๋ ฅํ๋ค. ํฌ๋งท ๋ณ๊ฒฝ ๊ธ์ง. โน๏ธ ์ ์ฌ ์ฐ๋ฝ์ฒ ๋ฐ๊ฒฌ ๊ธฐ์กด: ๐ค ํ๊ธธ๋ ๐ฑ +82-10-9999-0000 ์ด๋ฒ ๋ช ํจ: ๐ค #ํ๊ธธ๋ ๊ณผ์ฅ (ABC์ฃผ์ํ์ฌ) ๐ฑ +82-10-1234-5678 ๋ฒํธ๊ฐ ๋ค๋ฆ. ๊ทธ๋๋ก ์๋ก ์ ์ฅํ ๊น?
์ค๋ณต ์์ผ๋ฉด ์ค๋ณต ๊ด๋ จ ๋ฉ์์ง ์์ฒด๋ฅผ ์ถ๋ ฅํ์ง ์๋๋ค. ๋ฐ๋ก ์ฌ์ฉ์ ํ์ธ์ผ๋ก ๋์ด๊ฐ๋ค.
Maton API Gateway (People API)๋ฅผ ์ฌ์ฉ. ์ ์ฒด ํ๋ + ์ปค์คํ Name + ์ฌ์ง ์ง์.
python <<'EOF' import urllib.request, os, json # ํ๊ตญ์ ๋ช ํจ ์์ (koreanStyleName=true) contact = { "names": [{ "unstructuredName": "#ํ๊ธธ๋ ๊ณผ์ฅ", "givenName": "ํ๊ธธ๋", "familyName": "" }], "organizations": [{ "name": "ABC์ฃผ์ํ์ฌ", "title": "๊ณผ์ฅ", "department": "์์ ๋ถ", "type": "work" }], "emailAddresses": [ {"value": "gdhong@example.co.kr", "type": "work"} ], "phoneNumbers": [ {"value": "+82-10-1234-5678", "type": "mobile"}, {"value": "+82-2-9876-5432", "type": "work"} ], "addresses": [ {"formattedValue": "์์ธ์ ๊ฐ๋จ๊ตฌ ํ ํค๋๋ก 123", "type": "work"} ], "urls": [ {"value": "https://www.example.co.kr", "type": "work"} ] } data = json.dumps(contact).encode() req = urllib.request.Request( 'https://gateway.maton.ai/google-contacts/v1/people:createContact', data=data, method='POST' ) req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') result = json.load(urllib.request.urlopen(req)) print(json.dumps(result, indent=2)) EOF
Section 8์ ํ์ดํ๋ผ์ธ์ ๋ฐ๋ฅธ๋ค. ๋ณด์ + ์ ๋ก๋๋ Section 8์์ ์ผ๊ด ์ฒ๋ฆฌ. ํ์ดํ๋ผ์ธ ์ข ๋ฃ ์ (์ฑ๊ณต, ์ทจ์, ์๋ฌ ๋ฌด๊ด) $BIZCARD_TMP ๋๋ ํฐ๋ฆฌ ์ ์ฒด ์ญ์ (rm -rf "$BIZCARD_TMP"). ๋ค๋ฅธ ์ธ์ ์ ํ์ผ์ ๊ฑด๋๋ฆฌ์ง ์๋๋ค.
์ฌ์ฉ์๊ฐ /bizcard config ๋๋ "๋ช ํจ ์ค์ "์ ์ ๋ ฅํ๋ฉด, ์๋ ํ ํ๋ฆฟ์ ๊ทธ๋๋ก ๋ณต์ฌํด์ ์ถ๋ ฅํ๋ค. ์ ๋ ๋ค๋ฅธ ํฌ๋งท์ผ๋ก ๋ฐ๊พธ์ง ๋ง๋ผ. on/off ๊ฐ๋ง config.json ์ค์ ์ํ์ ๋ง์ถฐ ๊ต์ฒด. ์ถ๋ ฅ ํ ํ๋ฆฟ (์ด ํฌ๋งท ๊ทธ๋๋ก ์ฌ์ฉ): ๐ Bizcard Settings 1. Hashtag : on ๐ข โ #์ด๋ฆ (์นด์นด์ค ์๋์ถ๊ฐ ๋ฐฉ์ง) 2. Append title : on ๐ข โ ์ด๋ฆ ๋ค์ ์งํจ 3. Append company : off โ โ ์ด๋ฆ ๋ค์ (ํ์ฌ๋ช ) 4. Card as photo : on ๐ข โ ๋ช ํจโ์ฐ๋ฝ์ฒ ์ฌ์ง 5. Korean reading : on ๐ข โ ์ธ๊ตญ ์ด๋ฆ ํ๊ตญ์ด ๋ ์ 6. Korean style name : on ๐ข โ ์ฑ ๋น์, ์ด๋ฆ์ ํ๋ค์ 00 = Reset โบ 38 = All on ๐ข 49 = All off โ ๋ฒํธ๋ง ์ ๋ ฅํ๋ฉด onโoff ์ ํ. ์ด๋ชจ์ง ๊ท์น: on โ ๐ข, off โ โ. ๊ฐ ๋ฐ๋ก ๋ค์ ์ด๋ชจ์ง ๋ถ์ธ๋ค. ๊ท์น: ๋ฒํธ, ํญ๋ชฉ๋ช , ์ค๋ช ์ ๊ณ ์ . ๋ณ๊ฒฝ ๊ธ์ง. on / off ๊ฐ๋ง config.json ์ค์ ์ํ์ ๋ง์ถฐ ์ถ๋ ฅ. ๋ถ๋ฆฟ ๋ฆฌ์คํธ(โข)๋ ๋ค๋ฅธ ํฌ๋งท์ผ๋ก ๋ณํ ๊ธ์ง. ๋ถ๊ฐ ์ค๋ช ์ด๋ "์ํ๋ฉด ๋ฐ๊ฟ์ค๊ฒ" ๊ฐ์ ๋ฉํธ ์ถ๊ฐ ๊ธ์ง.
๋ฒํธ๋ง ์ ๋ ฅํ๋ฉด ํ์ฌ ์ํ์ ๋ฐ๋๋ก ์๋ ์ ํ๋๋ค. config.json ํ์ผ์ ์ค์ ๋ก ์์ ํ๊ณ , ์๋ ์๋ต ํฌ๋งท ๊ทธ๋๋ก ์ถ๋ ฅ. ์ธ์ ๊ท์น: /bizcard config ์คํ ํ ๋ค์ 1ํ ์ ๋ ฅ๋ง ์ค์ ๋ณ๊ฒฝ์ผ๋ก ์ฒ๋ฆฌํ๋ค. ๊ทธ ์ดํ์ ์ซ์ ์ ๋ ฅ์ ์ผ๋ฐ ๋ํ๋ก ์ทจ๊ธ. ์ค์ ์ ์ฐ์ ๋ณ๊ฒฝํ๋ ค๋ฉด /bizcard config๋ฅผ ๋ค์ ์ ๋ ฅ. ์์ 1: ํ์ฌ 3. Append company : off ์ํ์์ ์ฌ์ฉ์๊ฐ 3 ์ ๋ ฅ ์๋ต (์ด ํฌ๋งท ๊ทธ๋๋ก): 3. Append company : on ๐ข All set now. ์์ 2: ํ์ฌ 1. Hashtag : on ์ํ์์ ์ฌ์ฉ์๊ฐ 1 ์ ๋ ฅ ์๋ต (์ด ํฌ๋งท ๊ทธ๋๋ก): 1. Hashtag : off โ All set now. ๊ท์น: ๋ณ๊ฒฝ๋ ํญ๋ชฉ๋ง ํ ์ค ์ถ๋ ฅ + "All set now." ๊ทธ ์ธ ์ถ๊ฐ ๋ฉํธ ๊ธ์ง.
์ฝ๋๋์์ค๋ช 00Reset๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ด๊ธฐํ38All on์ ์ฒด ์ค์ ์ผ๊ธฐ49All off์ ์ฒด ์ค์ ๋๊ธฐ ์ ๋ ฅ: 49 ์๋ต: ๐ Bizcard Settings 1. Hashtag : off โ โ #์ด๋ฆ (์นด์นด์ค ์๋์ถ๊ฐ ๋ฐฉ์ง) 2. Append title : off โ โ ์ด๋ฆ ๋ค์ ์งํจ 3. Append company : off โ โ ์ด๋ฆ ๋ค์ (ํ์ฌ๋ช ) 4. Card as photo : off โ โ ๋ช ํจโ์ฐ๋ฝ์ฒ ์ฌ์ง 5. Korean reading : off โ โ ์ธ๊ตญ ์ด๋ฆ ํ๊ตญ์ด ๋ ์ 6. Korean style name : off โ โ ์ฑ ๋น์, ์ด๋ฆ์ ํ๋ค์ 00 = Reset โบ 38 = All on ๐ข 49 = All off โ All off. All set now. ์ ๋ ฅ: 00 ์๋ต: ๐ Bizcard Settings (defaults) 1. Hashtag : on ๐ข โ #์ด๋ฆ (์นด์นด์ค ์๋์ถ๊ฐ ๋ฐฉ์ง) 2. Append title : on ๐ข โ ์ด๋ฆ ๋ค์ ์งํจ 3. Append company : off โ โ ์ด๋ฆ ๋ค์ (ํ์ฌ๋ช ) 4. Card as photo : on ๐ข โ ๋ช ํจโ์ฐ๋ฝ์ฒ ์ฌ์ง 5. Korean reading : on ๐ข โ ์ธ๊ตญ ์ด๋ฆ ํ๊ตญ์ด ๋ ์ 6. Korean style name : on ๐ข โ ์ฑ ๋น์, ์ด๋ฆ์ ํ๋ค์ 00 = Reset โบ 38 = All on ๐ข 49 = All off โ Reset to defaults. All set now.
#config key์ค๋ช 1hashtag์ด๋ฆ ์์ # ์ถ๊ฐ (์นด์นด์คํก ์๋์ถ๊ฐ ๋ฐฉ์ง)2appendTitle์ด๋ฆ ๋ค์ ์งํจ ์ถ๊ฐ3appendCompany์ด๋ฆ ๋ค์ (ํ์ฌ๋ช ) ์ถ๊ฐ4cardAsPhoto๋ช ํจ ์ด๋ฏธ์ง๋ฅผ ์ฐ๋ฝ์ฒ ์ฌ์ง์ผ๋ก ์ ์ฅ5koreanReading์ธ๊ตญ ๋ช ํจ ์ด๋ฆ/ํ์ฌ๋ฅผ ํ๊ตญ์ด ๋ ์์ผ๋ก ๊ธฐ๋ก6koreanStyleNameํ๊ตญ ๋ช ํจ: familyName ๋น์ฐ๊ณ givenName์ ํ๋ค์
{ "hashtag": true, "appendTitle": true, "appendCompany": false, "cardAsPhoto": true, "koreanReading": true, "koreanStyleName": true }
์ฌ์ฉ์๊ฐ ์ฒ์ ๋ช ํจ์ ๋ณด๋ผ ๋ (bizcard-log.jsonl์ด ์๊ฑฐ๋ ๋น์ด์์ ๋): ๐ ๋ช ํจ ์ค์บ๋ ์ฒซ ์ฌ์ฉ! ๊ธฐ๋ณธ ์ค์ : 1. Hashtag : on 2. Append title : on 3. Append company : off 4. Card as photo : on 5. Korean reading : on 6. Korean style name : on ์ค์ ๋ณ๊ฒฝ: /bizcard config ์ด ๋ช ํจ ์ฒ๋ฆฌํ ๊น? ์ดํ์๋ ์จ๋ณด๋ฉ ์์ด ๋ฐ๋ก ์ฒ๋ฆฌ.
์ ์ฅ ์ฑ๊ณต ์ memory/bizcard-log.jsonl์ ์ต์ํ์ ์ ๋ณด๋ง ๊ธฐ๋กํ๋ค. ์ด๋ฉ์ผ, ์ ํ๋ฒํธ ๋ฑ ๋ฏผ๊ฐํ PII๋ ์ ์ฅํ์ง ์๋๋ค. ์์ธ ์ ๋ณด๋ Google Contacts์์ resourceName์ผ๋ก ์กฐํ. {"ts": "2026-02-20T14:30:00Z", "name": "ํ๊ธธ๋", "company": "ABC์ฃผ์ํ์ฌ", "resourceName": "people/c1234567890"} PII ์ต์ํ ์์น: ๋ก๊ทธ์๋ ์ด๋ฆ๊ณผ ํ์ฌ๋ช (๊ฒ์์ฉ)๋ง ๋จ๊ธฐ๊ณ , ์ ํ๋ฒํธ/์ด๋ฉ์ผ/์ฃผ์๋ ์ ์ฅํ์ง ์๋๋ค.
๋ช ๋ น๋์"๋ช ํจ ๊ฒ์ ํ๊ธธ๋" / "bizcard search ํ๊ธธ๋"People API searchContacts ์คํ"์ต๊ทผ ๋ช ํจ" / "recent bizcards"bizcard-log.jsonl์์ ์ต๊ทผ 10๊ฑด ํ์
์๋ฌ ์ํฉ์ฌ์ฉ์ ๋ฉ์์งOCR ์คํจ / ๋น ๊ฒฐ๊ณผ"ํ ์คํธ๋ฅผ ์ธ์ํ์ง ๋ชปํ์ด. ๋ ์ ๋ช ํ ์ฌ์ง์ผ๋ก ๋ค์ ๋ณด๋ด์ค"Maton API ์คํจ"Google Contacts ์ฐ๊ฒฐ์ ํ์ธํด์ค. API ํค๋ OAuth๊ฐ ๋ง๋ฃ๋์ ์ ์์ด"๋น ๋ช ํจ (์ ๋ณด ์์)"์ฐ๋ฝ์ฒ ์ ๋ณด๋ฅผ ๋ชป ์ฐพ์์ด. ๋ช ํจ์ด ๋ง๋์ง ํ์ธํด์ค"๋คํธ์ํฌ ์ค๋ฅ"๋คํธ์ํฌ ์ฐ๊ฒฐ์ ํ์ธํด์ค"์ฌ์ง ์ ๋ก๋ ์คํจ (์ฐ๋ฝ์ฒ๋ ์ ์ฅ๋จ)"์ฐ๋ฝ์ฒ๋ ์ ์ฅ๋๋๋ฐ ์ฌ์ง ์ ๋ก๋๊ฐ ์คํจํ์ด. ๋ค์ ์๋ํ ๊น?"config.json ํ์ฑ ์ค๋ฅ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์๋ ๋ณต๊ตฌ ํ "์ค์ ํ์ผ์ด ์์๋ผ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ณต๊ตฌํ์ด"
์ค์ ํ์ผ: skills/bizcard/config.json #key๊ธฐ๋ณธ๊ฐ์ค๋ช 1hashtagtrue์ด๋ฆ ์์ # ์ถ๊ฐ (์นด์นด์คํก ์๋์ถ๊ฐ ๋ฐฉ์ง)2appendTitletrue์ด๋ฆ ๋ค์ ์งํจ ์ถ๊ฐ3appendCompanyfalse์ด๋ฆ ๋ค์ (ํ์ฌ๋ช ) ์ถ๊ฐ4cardAsPhototrue๋ช ํจ ์ด๋ฏธ์ง๋ฅผ ์ฐ๋ฝ์ฒ ์ฌ์ง์ผ๋ก ์ ์ฅ5koreanReadingtrue์ธ๊ตญ ๋ช ํจ ์ด๋ฆ/ํ์ฌ๋ฅผ ํ๊ตญ์ด ๋ ์์ผ๋ก ๊ธฐ๋ก6koreanStyleNametrueํ๊ตญ ๋ช ํจ: familyName ๋น์ฐ๊ณ givenName์ ํ๋ค์
ToolPurposeInstallMATON_API_KEYMaton API Gateway auth (People API proxy)maton.ai/settingsNANO_BANANA_API_KEYGoogle Gemini API key (used by Nano Banana Pro for image correction)aistudio.google.com
references/people-api-fields.md โ Google People API field reference Google People API docs
Agent frameworks, memory systems, reasoning layers, and model-native orchestration.
Largest current source with strong distribution and engagement signals.