一、环境检查

必备账号

[ ] Anthropic API key(console.anthropic.com)
[ ] Railway 账号(railway.app)
[ ] GitHub 账号(push 代码触发部署)
[ ] Mercury / Stripe / Wise(接收 SaaS 用户付款)

国内开发环境

Anthropic API 在国内 IP 直接调用受限。开发期需要稳定线路调试。

如果你需要稳定调试 Claude API + 同时管 Stripe / Wise / Mercury 等海外账户,配一条主推 GPT-5.5 / Claude 4.7 的低价 API 中转能保证开发联调不中断,同时省 40-60% API 成本。

二、初始化项目

mkdir my-claude-agent
cd my-claude-agent
npm init -y
npm install @anthropic-ai/sdk express dotenv
npm install -D typescript @types/node @types/express tsx

# tsconfig.json
cat > tsconfig.json << 'EOF'
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "esModuleInterop": true,
    "strict": true,
    "outDir": "dist"
  },
  "include": ["src/**/*"]
}
EOF

三、实现 Agent loop

// src/agent.ts
import Anthropic from '@anthropic-ai/sdk'

const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY })

const tools = [
  {
    name: 'get_weather',
    description: '获取指定城市的实时天气',
    input_schema: {
      type: 'object',
      properties: {
        city: { type: 'string', description: '城市名' }
      },
      required: ['city']
    }
  },
  {
    name: 'search_web',
    description: '搜索互联网获取最新信息',
    input_schema: {
      type: 'object',
      properties: {
        query: { type: 'string' }
      },
      required: ['query']
    }
  }
]

async function runAgent(userMessage: string) {
  const messages: any[] = [
    { role: 'user', content: userMessage }
  ]

  let iterations = 0
  const MAX_ITERATIONS = 20

  while (iterations++ < MAX_ITERATIONS) {
    const response = await client.messages.create({
      model: 'claude-opus-4-7',
      max_tokens: 4096,
      tools,
      messages
    })

    messages.push({ role: 'assistant', content: response.content })

    if (response.stop_reason === 'end_turn') {
      return response.content
    }

    if (response.stop_reason === 'tool_use') {
      const toolResults = []
      for (const block of response.content) {
        if (block.type === 'tool_use') {
          const result = await executeTool(block.name, block.input)
          toolResults.push({
            type: 'tool_result',
            tool_use_id: block.id,
            content: JSON.stringify(result)
          })
        }
      }
      messages.push({ role: 'user', content: toolResults })
    }
  }
  throw new Error('Max iterations reached')
}

async function executeTool(name: string, input: any) {
  if (name === 'get_weather') {
    return { temp: 22, city: input.city, condition: 'sunny' }
  }
  if (name === 'search_web') {
    return { results: [`Mock result for: ${input.query}`] }
  }
}

四、暴露为 HTTP API

// src/server.ts
import express from 'express'
import { runAgent } from './agent.js'

const app = express()
app.use(express.json())

app.post('/api/agent', async (req, res) => {
  const { message } = req.body
  try {
    const result = await runAgent(message)
    res.json({ result })
  } catch (err) {
    res.status(500).json({ error: String(err) })
  }
})

app.get('/health', (_, res) => res.json({ ok: true }))

const PORT = process.env.PORT || 3000
app.listen(PORT, () => console.log(`Listening on ${PORT}`))

五、Dockerfile(multi-stage 优化)

# Dockerfile
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./
EXPOSE 3000
CMD ["node", "dist/server.js"]
// package.json scripts
{
  "scripts": {
    "build": "tsc",
    "start": "node dist/server.js",
    "dev": "tsx watch src/server.ts"
  }
}

六、Railway 部署步骤

# 1. 推到 GitHub
git init
git add .
git commit -m "init claude agent"
git remote add origin [email protected]:you/my-claude-agent.git
git push -u origin main

# 2. 在 Railway 创建 project
# Dashboard → New → Deploy from GitHub repo
# 选择仓库 → Deploy

# 3. 配 env vars
ANTHROPIC_API_KEY=sk-ant-...
NODE_ENV=production

# 4. 选择 Domain
# Settings → Domain → Generate Domain

七、成本监控

// src/cost-tracker.ts
import fs from 'fs'

const PRICES = {
  'claude-opus-4-7': { input: 15 / 1e6, output: 75 / 1e6 },
  'claude-sonnet-4-6': { input: 3 / 1e6, output: 15 / 1e6 },
  'claude-haiku-4-5': { input: 0.8 / 1e6, output: 4 / 1e6 }
}

export function trackUsage(model: string, usage: any) {
  const price = PRICES[model as keyof typeof PRICES]
  const cost = price.input * usage.input_tokens + price.output * usage.output_tokens

  const log = {
    timestamp: new Date().toISOString(),
    model,
    input_tokens: usage.input_tokens,
    output_tokens: usage.output_tokens,
    cost_usd: cost.toFixed(6)
  }
  fs.appendFileSync('/tmp/usage.log', JSON.stringify(log) + '\n')
  return cost
}

八、单次任务成本对比

任务模型input tokensoutput tokens成本(直连)成本(中转 -50%)
简单问答Haiku 4.5200100$0.0006$0.0003
Web search agentSonnet 4.65,0002,000$0.045$0.022
Multi-step taskOpus 4.715,0005,000$0.60$0.30
长上下文代码分析Opus 4.7100,00010,000$2.25$1.13

九、生产级建议

维度建议
Model默认 Sonnet 4.6,复杂任务才升 Opus 4.7
Rate limitAnthropic 默认 50 RPM,需要时 contact 升级
Retry自动重试 5xx 错误 + exponential backoff
Logging记录每次 messages.create 的 token / cost
Monitoring用 Sentry 抓 tool_use 异常
Cost cap单用户单日 cap $5 / 单月 cap $50
Streaming用 messages.stream 给前端实时显示

关联文章

Claude Agent SDK Railway 部署的落地条件

Claude Agent SDK Railway 部署最怕把法律主体、收款工具和产品代码混成一个问题。动手前看清收款账户、税务资料和部署环境,金额较大或涉及税务时应交给专业顾问处理。

一个人运营时可以用表格压住复杂度:负责人、后台入口、到期日、费用来源和回滚动作各占一列,避免换服务商时才发现资料缺口。

涉及 Stripe、公司注册、税表或签证的内容,只能作为操作参考。当前页面没有覆盖你所在司法辖区的特殊规定时,不应把它当成法律或税务意见。

项目看什么不宜继续的信号
收款账户当前后台、日志或设置页里能直接看到的字段页面提示和手头资料对不上
税务资料费用、权限、地区或设备造成的实际影响已经影响付款、审核、生产环境或家庭使用
部署环境回退入口、旧配置、官方支持材料找不到回滚方式,或责任人无法确认